Synology, Docker and storage 11 min read

S3-compatible storage on a Synology NAS with RustFS

Deploying RustFS in Container Manager, publishing the S3 API and the console behind a reverse proxy, then creating a first bucket.

RustFS turns a Synology NAS into object storage compatible with the S3 API. This guide installs the service in Container Manager, properly separates the API from the Web console and publishes both behind the DSM reverse proxy.

What is RustFS?

RustFS is an open source object storage server written in Rust and distributed under the Apache 2.0 licence. Its S3 compatibility lets you use it with the many backup tools, applications and libraries designed for that API.

On a NAS, it can serve to centralise application backups, static files or archives. It does not, however, replace a backup strategy: the RustFS data itself must be copied to another device or another site.

Before you start

  • Install Container Manager from the DSM Package Center.
  • Prepare two DNS names, for example s3.example.be for the API and console-s3.example.be for administration.
  • Attach a valid TLS certificate to both names in DSM.
  • Choose long, unique credentials and keep them in a secret manager.
  • Plan an independent backup of the data folder before trusting important files to the service.

Preparing the folders

In File Station, create docker/rustfs, then two subfolders: data for the objects and logs for the logs. Adapt the volume name if your installation does not use volume1.

The data and logs folders of the RustFS project in File Station, shown in French
The project keeps the RustFS data and logs separate.

The official image runs the service with UID/GID 10001. The most restrictive solution is to grant write access only to that user on both folders:

sudo chown -R 10001:10001 /volume1/docker/rustfs/data /volume1/docker/rustfs/logs
sudo chmod -R u+rwX,go-rwx /volume1/docker/rustfs/data /volume1/docker/rustfs/logs

If you work only through the DSM interface, first make the inherited permissions explicit, then grant read and write access to the account or the group used by Container Manager. The following screenshots show the path in DSM. Avoid granting Everyone read/write access in production; if that setting is needed for a test, restrict it strictly to the rustfs folder.

Making inherited permissions explicit in DSM, shown in French
Make the inherited permissions explicit before adjusting them.
The DSM permission editor, shown in French
For production, prefer a dedicated account or group rather than Everyone.

Creating the project in Container Manager

In Container Manager → Project, choose Create, name the project rustfs and select the /docker/rustfs folder. Then paste this docker-compose.yml file:

services:
  rustfs:
    image: rustfs/rustfs:latest
    container_name: rustfs-server
    security_opt:
      - no-new-privileges:true
    ports:
      - "9000:9000" # S3 API
      - "9001:9001" # Web console
    environment:
      RUSTFS_VOLUMES: /data/rustfs0
      RUSTFS_ADDRESS: 0.0.0.0:9000
      RUSTFS_CONSOLE_ADDRESS: 0.0.0.0:9001
      RUSTFS_CONSOLE_ENABLE: "true"
      RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS: https://console-s3.example.be
      RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY}
      RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY}
    volumes:
      - ./data:/data/rustfs0
      - ./logs:/var/log/rustfs
    restart: unless-stopped

Create an .env file next to it. The values below are deliberately placeholders: replace them before starting the project and never publish that file.

RUSTFS_ACCESS_KEY=CHANGE_ME
RUSTFS_SECRET_KEY=GENERATE_A_LONG_UNIQUE_SECRET
Creating the RustFS project in Container Manager, shown in French
Create the project in /docker/rustfs and use the configuration above.
The Container Manager terminal reporting that RustFS has started
An exit code of 0 confirms the container was created.

Configuring the reverse proxy

In Control Panel → Login Portal → Advanced → Reverse Proxy, create two separate rules. This is the point not to get the wrong way round:

  • https://s3.example.be:443 to http://localhost:9000 for the S3 API.
  • https://console-s3.example.be:443 to http://localhost:9001 for the Web console.

For the console, add the WebSocket headers $http_upgrade and $connection_upgrade. Timeouts of 600 seconds suit long transfers, but adapt them to your environment. Then assign the right TLS certificate to both host names.

The reverse proxy rule for the RustFS console, shown in French
This rule shows the console on port 9001. Create a second rule for the API on port 9000.

Adapting the DSM firewall

Do not expose ports 9000 and 9001 directly to the internet. First allow HTTPS towards the reverse proxy, then restrict the internal ports to the NAS, the administration network or the Docker subnet actually in use.

To identify that network, open Container Manager → Network and expand the project network. In the example, 172.18.0.0/16 corresponds to the mask 255.255.0.0. Your value may differ: copy it exactly and place the allow rule before the deny rules.

The Docker subnet shown in Container Manager, in French
Note the real subnet of the project before changing the firewall.

Creating the first bucket

Open https://console-s3.example.be and sign in with the access key and the secret key set in .env. In Browser, create your first bucket, for example bucket01.

The RustFS sign-in page, shown fully translated into French
Sign in with the credentials kept in .env.
The bucket list in the RustFS console, shown in French
The first bucket appears in the object browser.

Then create an access key specific to the application that will use that bucket. The secret key is only displayed at the moment it is created: export it to your secret manager, then close the window. The values in the screenshot were deliberately masked.

Creating a RustFS access key with the secrets masked
Store the secret key immediately; the values shown are masked.
Choosing the policy of a RustFS bucket, shown in French
Keep the Private policy unless a public need has been explicitly validated.

Checking the service

RustFS exposes a health check for each interface. Both commands must answer without error:

curl -fsS https://s3.example.be/health
curl -fsS https://console-s3.example.be/rustfs/console/health

Then test an upload and a download with the S3 client you actually plan to use, and restart the container to confirm that the data persists in docker/rustfs/data.

In short

The deployment fits in a single Container Manager project, but three details make the difference: restricted permissions on the volumes, secrets kept out of the Compose file, and two properly separated proxy rules. The S3 API uses port 9000 and the console port 9001.

References

About the author

Jeremy Kraft runs the infrastructure and the self-hosted services of the IBCSC. These guides describe configurations that were actually deployed and re-checked before publication.

Discussion

Comments

0

No comment yet. Feel free to open the discussion with a question or your own experience.