This document outlines security best practices for deploying RustFS with the NixOS module.
❌ NEVER do this:
services.rustfs = {
accessKey = "rustfsadmin"; # INSECURE! Will be in Nix store!
secretKey = "rustfsadmin";
};✅ Always use file-based secrets:
services.rustfs = {
accessKeyFile = "/run/secrets/rustfs-access-key";
secretKeyFile = "/run/secrets/rustfs-secret-key";
};We recommend using one of the following tools for managing secrets:
sops-nix provides encrypted secrets management:
inputs.sops-nix.url = "github:Mic92/sops-nix";
imports = [ inputs.sops-nix.nixosModules.sops ];
sops.secrets.rustfs-access-key = {
sopsFile = ./secrets.yaml;
owner = config.services.rustfs.user;
group = config.services.rustfs.group;
mode = "0400";
};
sops.secrets.rustfs-secret-key = {
sopsFile = ./secrets.yaml;
owner = config.services.rustfs.user;
group = config.services.rustfs.group;
mode = "0400";
};
services.rustfs = {
enable = true;
accessKeyFile = config.sops.secrets.rustfs-access-key.path;
secretKeyFile = config.sops.secrets.rustfs-secret-key.path;
};agenix provides age-encrypted secrets:
inputs.agenix.url = "github:ryantm/agenix";
imports = [ inputs.agenix.nixosModules.default ];
age.secrets.rustfs-access-key = {
file = ./secrets/rustfs-access-key.age;
owner = config.services.rustfs.user;
group = config.services.rustfs.group;
mode = "0400";
};
age.secrets.rustfs-secret-key = {
file = ./secrets/rustfs-secret-key.age;
owner = config.services.rustfs.user;
group = config.services.rustfs.group;
mode = "0400";
};
services.rustfs = {
enable = true;
accessKeyFile = config.age.secrets.rustfs-access-key.path;
secretKeyFile = config.age.secrets.rustfs-secret-key.path;
};For simpler deployments, you can manually create secret files:
# Create secret files with proper permissions
sudo mkdir -p /run/secrets
echo "your-access-key" | sudo tee /run/secrets/rustfs-access-key
echo "your-secret-key" | sudo tee /run/secrets/rustfs-secret-key
sudo chown rustfs:rustfs /run/secrets/rustfs-*
sudo chmod 400 /run/secrets/rustfs-*The RustFS NixOS module implements extensive systemd security hardening. The service runs with:
- Non-root user: Service runs as dedicated
rustfsuser - No capabilities:
CapabilityBoundingSet = "" - Private /tmp:
PrivateTmp = true - Private /dev:
PrivateDevices = true - Read-only system:
ProtectSystem = "strict"with explicit write paths - No privilege escalation:
NoNewPrivileges = true - Restricted system calls:
SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ] - Memory protections:
MemoryDenyWriteExecute = true - Network restrictions: Only AF_INET, AF_INET6, and AF_UNIX allowed
See the full list in nixos/rustfs.nix.
The module automatically configures secure file permissions:
# Directories are created with restrictive permissions
systemd.tmpfiles.rules =
(lib.optional (cfg.logDirectory != null)
"d ${cfg.logDirectory} 0750 ${cfg.user} ${cfg.group} -")
++ [
"d ${cfg.tlsDirectory} 0750 ${cfg.user} ${cfg.group} -"
"d ${volume} 0750 ${cfg.user} ${cfg.group} -" # For each volume
];For production deployments, always use TLS:
services.rustfs = {
enable = true;
# ... other options ...
tlsDirectory = "/etc/rustfs/tls";
};
# Place your certificates in /etc/rustfs/tls/
# - server.crt
# - server.key
# - ca.crt (optional)Restrict network access using NixOS firewall:
networking.firewall = {
enable = true;
allowedTCPPorts = [ 9000 9001 ]; # API port and console port
# Or use interfaces for more granular control
interfaces.eth0.allowedTCPPorts = [ 9000 9001 ];
};For console access, consider binding to localhost only:
services.rustfs = {
consoleAddress = "127.0.0.1:9001"; # Localhost only
};Then use SSH port forwarding to access the console:
ssh -L 9001:localhost:9001 your-serverUse appropriate volume locations:
services.rustfs = {
# ❌ Bad - temporary storage
volumes = "/tmp/rustfs";
# ✅ Good - persistent storage with proper permissions
volumes = "/var/lib/rustfs";
# ✅ Also good - multiple volumes
volumes = [ "/mnt/storage1" "/mnt/storage2" ];
};Ensure volumes have appropriate filesystem permissions and are on encrypted filesystems for sensitive data.
By default, logs are written to systemd journal with restricted access:
services.rustfs = {
# Default: logs go to systemd journal (journalctl -u rustfs)
logLevel = "info"; # Don't use "debug" or "trace" in production
};
# View logs with journalctl
# journalctl -u rustfs -f # Follow logs in real-time
# journalctl -u rustfs --since today # Today's logsFor file-based logging with rotation:
services.rustfs = {
logDirectory = "/var/log/rustfs"; # Enable file logging
logLevel = "info";
};
services.logrotate = {
enable = true;
settings.rustfs = {
files = "/var/log/rustfs/*.log";
frequency = "daily";
rotate = 7;
compress = true;
delaycompress = true;
missingok = true;
notifempty = true;
create = "0640 rustfs rustfs";
};
};Keep RustFS updated:
services.rustfs.package = inputs.rustfs.packages.${pkgs.stdenv.hostPlatform.system}.default;Regularly update your flake inputs:
nix flake update
nixos-rebuild switchIf you discover a security vulnerability in the RustFS NixOS module, please report it to the RustFS security team. Do not open a public GitHub issue.
Before deploying to production, ensure:
- Secrets are stored in files, not in Nix configuration
- Secret files have permissions 0400 and correct ownership
- Using a secret management tool (sops-nix, agenix, etc.)
- TLS/HTTPS is configured for API and console
- Firewall rules are properly configured
- Console is not exposed to public internet
- Log level is not set to "debug" or "trace"
- Volumes are on persistent, secure storage
- Log rotation is configured
- System is kept up-to-date
If you're migrating from an old configuration using accessKey and secretKey options:
- Create secret files:
echo "your-access-key" | sudo tee /run/secrets/rustfs-access-key
echo "your-secret-key" | sudo tee /run/secrets/rustfs-secret-key
sudo chown rustfs:rustfs /run/secrets/rustfs-*
sudo chmod 400 /run/secrets/rustfs-*- Update configuration:
services.rustfs = {
# Remove these:
# accessKey = "...";
# secretKey = "...";
# Add these:
accessKeyFile = "/run/secrets/rustfs-access-key";
secretKeyFile = "/run/secrets/rustfs-secret-key";
};- Rebuild and verify:
sudo nixos-rebuild switch
sudo systemctl status rustfs