LowEndBuckets: Setting Up an Maintainable Minio

MinIO is self-hosted S3-compatible object storage.  You can set it up in minutes and your VPS will look and act just like Amazon S3 storage, compatible with many backup programs and applications.  In this tutorial, we’ll setup MinIO and do so in a secure, encrypted, and maintainable fashion.

We’re using:

  • A Debian 10 VPS called storage.lowend.party
  • /etc/minio for MinIO config files
  • /usr/local/bin for the MinIO binary
  • /data for MinIO storage

This is actually not my preferred MinIO config (I prefer to have everything MinIO-related under /minio, with /minio/bin, /minio/data, /minio/etc, etc.)  However, by using the default configs, we can save a great deal of time and you can always tweak later.

You shouldn’t run MinIO as root, so let’s create a MinIO user.

useradd -r -s /sbin/nologin minio-user

Now create required directories and make minio-user the owner.

mkdir /data /etc/minio
chown minio-user:minio-user /data /etc/minio

Next, we’ll download the MinIO binary:

wget -O /usr/local/bin/minio https://dl.min.io/server/minio/release/linux-amd64/minio
chmod 755 minio

Now we need to specify options to pass to the systemd startup.  We do this by creating /etc/default/minio and populating it as follows:

MINIO_OPTS="-C /etc/minio --address storage.lowend.party:9000"

Obviously, you’ll want to change MINIO_ACCESS_KEY and set a significantly more complex password for MINIO_SECRET_KEY.

Next, grab the MinIO systemd unit file and put it in /etc/systemd/service:

wget -O /etc/systemd/service/minio.service https://raw.githubusercontent.com/minio/minio-service/master/linux-systemd/minio.service

If you’ve used all the config I’ve specific, this unit file will work without modification, but if you’ve changed paths, MinIO user name, etc., you’ll need to tweak this file.  When it’s as you like, load it into systemctl:

systemctl daemon-reload

Before we fire up MinIO, let’s make sure our connections are encrypted.  We’ll use Let’s Encrypt for this.

apt -y install certbot

Now run the certbot standalone web server:

certbot certonly --standalone -d storage.lowend.party

Enter your email, accept the terms, and decide if you want EFF spam:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): raindog308@raindog308.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: a

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: n
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for storage.lowend.party
Waiting for verification...
Cleaning up challenges


- Congratulations! Your certificate and chain have been saved at:
Your key file has been saved at:
Your cert will expire on 2020-09-26. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

We have a small problem, in that MinIO needs access to the certs but they’re going to change every 90 days.  We don’t want the hassle of manually copying, chmodding, etc. every 90 days, so let’s automate this.

If you look in /etc/letsencrypt/live (where the certs live), you’ll see that the certs are actually symlinks, and they point to files (in /etc/letsencrypt/storage/archive) whose names change, so we can’t simply symlink to the symlink because symlink permissions aren’t really permissions.  We’ll need to create a short script to solve the problem.

Put this in a file called /usr/local/bin/maintain_minio_certs.sh


cp /etc/letsencrypt/live/storage.lowend.party/privkey.pem /etc/minio/certs/private.key
chown minio-user:minio-user /etc/minio/certs/private.key
cp /etc/letsencrypt/live/storage.lowend.party/fullchain.pem /etc/minio/certs/public.crt
chown minio-user:minio-user /etc/minio/certs/public.crt
systemctl restart minio

Save it, and then

chmod 755 /usr/local/bin/maintain_minio_certs.sh

We could schedule it to run regularly, but an easier method is to link it in to the certbot service itself.  This way, every time certbot updates, this script will run.

Modify /lib/systemd/service/certbot.service and add the ExecStartPost line shown below:

ExecStart=/usr/bin/certbot -q renew 

Now reload the unit file:

systemctl daemon-reload

And run

systemctl start certbot

After that, you can see that the certificates are now properly installed:

root@storage:/lib/systemd/system# ls -l /etc/minio/certs/
total 20
drwx------ 3 minio-user minio-user 4096 Jun 28 10:08 .
drwxr-xr-x 3 minio-user minio-user 4096 Jun 28 09:37 ..
drwx------ 2 minio-user minio-user 4096 Jun 28 09:37 CAs
-rw------- 1 minio-user minio-user 1704 Jun 28 10:08 private.key
-rw-r--r-- 1 minio-user minio-user 3574 Jun 28 10:08 public.crt

At this point, you’re ready to fire up MinIO:

systemctl start minio

Your MinIO server should now be running on port 9000.  Start a web browser and navigate to https://your-server-name:9000 and you should be able to log into MinIO:



I’m Andrew, techno polymath and long-time LowEndTalk community Moderator. My technical interests include all things Unix, perl, python, shell scripting, and relational database systems. I enjoy writing technical articles here on LowEndBox to help people get more out of their VPSes.

Drupal 7 S3FS connection to use Minio as local S3 service

Can anyone please offer help or advice on how to configure region data for a Minio S3 bucket?

I’m working on a Drupal 7 site powered by Docker. The drupal frontend and mysql are on seperate containers.
I have also added a Minio container for local S3 testing.

The issue I’m having is the S3FS refuses to save my local configuration settings because it reports the following error:

This bucket exists, but it is not in the specified region.

enter image description here

However, I can’t set a region for my bucket. There is no region option in the minio interface:
enter image description here

And, I can’t get into the docker container to investigate if the region is configurable from there. I tried both following commands:

docker exec -it 8c3 bash
docker exec -it 8c3 /bin/sh

And recieved the following message, preventing me from getting into the container:

unexpected EOF

Minio: how to generate read-only access for duplication

Since I have a PRIMARY server and a REPLICA.
When I need to run a MIRROR server, I want for security reasons to have ONLY READ ACCESS

Q: How to generate a second pair of passcode and secret passcode for read-only access?

Thanks for your help!

amazon s3 – How to find the source of the SignatureDoesNotMatch error in Minio

For more than a year, we executed a one-page application (SPA with Angular) that receives Json objects with preset urls from a basic .NET API. The SPA displays a list and uses the preset URL to display the image / video (downloaded directly from the

Suddenly, some of the URLs preset in the list still work, others cause a SignatureDoesNotMatch error when the image / video is embedded. The others work.

SignatureDoesNotMatchThe request signature we calculate does not match the signature you provided. Check your password and signature method....

Maybe someone has experience with Minio / S3 and can help me create a checklist to find the source of this error.

So far I have:

  1. Configuration (password, secret key, host): since most URLs work, some should not be valid

  2. Url generation: for work url and not work url, I generate them using the Minio .NET SDK (3.02).

awaits _minio.PresignedGetObjectAsync (bucket, key, ttl);
awaits _minio.PresignedPutObjectAsync (bucket, key, ttl); 
  1. Mix get and put urls: Could it be a reason? The screenshots of the error report showed the urls preset, but I have not seen an indicator in the url if it was generated as put u get url.