Skip to content

Commit e09095d

Browse files
housemeCopilot
andauthored
refactor: Issue #9 improvements and documentation reorganization (#15)
* feat: Issue #9 improvements and documentation reorganization - Remove manual binary stripping and binutils - Clarify sourceProvenance for pre-compiled binaries - Migrate to environment attribute set (nixpkgs best practice) - Replace shell script with %d placeholder - Default to systemd journal logging - Move detailed docs to docs/, remove duplicates - Update all documentation references * fix: combine duplicate allowedTCPPorts into single list in firewall example (#16) * Initial plan * fix: combine duplicate allowedTCPPorts into single list in firewall example Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * fix: address PR #15 review feedback — secrets handling, broken links, optional logDirectory (#17) * Initial plan * fix: address remaining review comments - secrets handling, broken links, optional logDirectory Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * fix: clarify CHANGELOG deprecated accessKey/secretKey semantics and required file path Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * fix: remove hardcoded secrets from activation script example; align README with LoadCredential behavior Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * add workflows config * fix: CI — nixpkgs-fmt formatting violations and mkRenamedOptionModule arity (#18) * Initial plan * fix: resolve CI errors — invalid checkout@v6 and mkRenamedOptionModule 3-arg call Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * fix: apply nixpkgs-fmt to all 3 failing files and restore checkout@v6 Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: houseme <4829346+houseme@users.noreply.github.com>
1 parent 6e8af16 commit e09095d

13 files changed

Lines changed: 1976 additions & 99 deletions

File tree

.github/workflows/ci.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Copyright 2024 RustFS Team
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
name: CI
16+
17+
on:
18+
pull_request:
19+
push:
20+
branches:
21+
- main
22+
workflow_dispatch:
23+
24+
permissions:
25+
contents: read
26+
27+
concurrency:
28+
group: ci-${{ github.workflow }}-${{ github.ref }}
29+
cancel-in-progress: true
30+
31+
jobs:
32+
lint-and-eval:
33+
name: Lint and Evaluate
34+
runs-on: ubuntu-latest
35+
36+
steps:
37+
- name: Checkout repository
38+
uses: actions/checkout@v6
39+
40+
- name: Install Nix
41+
uses: cachix/install-nix-action@v25
42+
with:
43+
nix_path: nixpkgs=channel:nixos-unstable
44+
45+
- name: Check Nix formatting
46+
run: nix shell nixpkgs#nixpkgs-fmt -c nixpkgs-fmt --check .
47+
48+
- name: Evaluate flake outputs
49+
run: nix flake check --no-build
50+
51+
- name: Evaluate example configuration
52+
run: |
53+
cd examples
54+
nix eval .#nixosConfigurations.example-host.config.services.rustfs.enable
55+
56+
build-linux-package:
57+
name: Build Linux package
58+
runs-on: ubuntu-latest
59+
needs: lint-and-eval
60+
61+
steps:
62+
- name: Checkout repository
63+
uses: actions/checkout@v6
64+
65+
- name: Install Nix
66+
uses: cachix/install-nix-action@v25
67+
with:
68+
nix_path: nixpkgs=channel:nixos-unstable
69+
70+
- name: Build rustfs package (x86_64-linux)
71+
run: nix build .#packages.x86_64-linux.default --print-build-logs
72+

.github/workflows/update-sources.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
for system in "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin"; do
7272
FILE_NAME=$(jq -r --arg sys "$system" '.files[$sys].name' sources.json.new)
7373
URL="https://github.com/$REPO/releases/download/$VERSION/$FILE_NAME"
74-
74+
7575
echo "Fetching hash for $URL..."
7676
# Get base32 hash from nix-prefetch-url and convert to hex (base16)
7777
BASE32_HASH=$(nix-prefetch-url --type sha256 "$URL")
@@ -85,6 +85,13 @@ jobs:
8585
echo "updated=true" >> $GITHUB_OUTPUT
8686
echo "version=$VERSION" >> $GITHUB_OUTPUT
8787
88+
- name: Validate updated flake and example
89+
if: steps.update_script.outputs.updated == 'true'
90+
run: |
91+
nix flake check --no-build
92+
cd examples
93+
nix eval .#nixosConfigurations.example-host.config.services.rustfs.enable
94+
8895
- name: Clean up Git credentials
8996
run: git config --local --unset-all http.https://github.com/.extraheader || true
9097

@@ -102,8 +109,11 @@ jobs:
102109
body: |
103110
## Description
104111
Automated update of RustFS binaries to version `${{ steps.update_script.outputs.version }}`.
105-
112+
106113
Verified SHA256 hashes (Hex format) for all platforms.
114+
Validation passed:
115+
- `nix flake check --no-build`
116+
- `examples` flake service evaluation
107117
labels: |
108118
dependencies
109119
automated-pr

CHANGELOG.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Changelog
2+
3+
All notable changes to the RustFS NixOS module will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Recent Improvements (March 2026)
11+
12+
Following community feedback on Issue #9, additional improvements aligned with Nix best practices:
13+
14+
#### Removed Manual Binary Stripping
15+
16+
- Removed redundant manual `strip` command and `binutils` dependency
17+
- Nix automatically strips binaries by default
18+
- Allows packages to use `dontStrip` for debugging when needed
19+
20+
#### Clarified sourceProvenance
21+
22+
- Added clear documentation explaining pre-compiled binaries from GitHub releases
23+
- Makes it obvious why `sourceProvenance = [ sourceTypes.binaryNativeCode ]` is declared
24+
25+
#### Migrated to Environment Attribute Set
26+
27+
- Changed from `serviceConfig.Environment` list to `environment` attribute set
28+
- More idiomatic Nix style following nixpkgs conventions
29+
- Better integration with override system
30+
- Follows patterns from minio and other modules
31+
32+
#### Replaced Shell Script with %d Placeholder
33+
34+
- Eliminated `pkgs.writeShellScript` wrapper for credential loading
35+
- Uses systemd's `%d` placeholder for credentials directory
36+
- Cleaner implementation: `RUSTFS_ACCESS_KEY = "file:%d/access-key"`
37+
- Direct binary execution without wrapper script
38+
39+
#### Default to Systemd Journal Logging
40+
41+
- Changed `logDirectory` default from `"/var/log/rustfs"` to `null`
42+
- Logs written to systemd journal by default
43+
- View logs with: `journalctl -u rustfs -f`
44+
- File logging still available when explicitly configured
45+
- Automatic log rotation and unified log management
46+
47+
### Added
48+
49+
- Comprehensive security documentation in `docs/SECURITY.md`
50+
- Migration guide for users upgrading from insecure configuration in `docs/MIGRATION.md`
51+
- Example configurations with sops-nix integration
52+
- Support for both file-based and sops-nix/agenix secret management
53+
- Systemd LoadCredential for secure secret passing
54+
- Extensive systemd security hardening:
55+
- `CapabilityBoundingSet = ""`
56+
- `PrivateDevices = true`
57+
- `PrivateTmp = true`
58+
- `PrivateUsers = true`
59+
- `ProtectSystem = "strict"`
60+
- `ProtectHome = true`
61+
- `ProtectKernelTunables = true`
62+
- `ProtectKernelModules = true`
63+
- `ProtectKernelLogs = true`
64+
- `ProtectClock = true`
65+
- `ProtectControlGroups = true`
66+
- `ProtectHostname = true`
67+
- `ProtectProc = "invisible"`
68+
- `ProcSubset = "pid"`
69+
- `RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]`
70+
- `RestrictNamespaces = true`
71+
- `RestrictRealtime = true`
72+
- `RestrictSUIDSGID = true`
73+
- `SystemCallArchitectures = "native"`
74+
- `SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]`
75+
- `MemoryDenyWriteExecute = true`
76+
- `LockPersonality = true`
77+
- `NoNewPrivileges = true`
78+
- `UMask = "0077"`
79+
- `ReadWritePaths` configuration for explicit write access
80+
- Resource limits: `LimitNOFILE = 1048576`, `LimitNPROC = 32768`
81+
- Improved restart configuration with `RestartSec = "10s"`
82+
- Timeout configurations: `TimeoutStartSec = "60s"`, `TimeoutStopSec = "30s"`
83+
- Automatic directory creation with secure permissions via `systemd.tmpfiles.rules`
84+
- Detailed option descriptions with examples
85+
- Security checklist in documentation
86+
- Log rotation example configuration
87+
88+
### Changed
89+
90+
- **Deprecated**: `services.rustfs.accessKey` is renamed to `services.rustfs.accessKeyFile` via `mkRenamedOptionModule`. The old name now maps to the *file path* option — plain-text secret strings are no longer accepted. A valid file path is required whenever `services.rustfs.enable = true`.
91+
- **Deprecated**: `services.rustfs.secretKey` is renamed to `services.rustfs.secretKeyFile` via `mkRenamedOptionModule`. The old name now maps to the *file path* option — plain-text secret strings are no longer accepted. A valid file path is required whenever `services.rustfs.enable = true`.
92+
- Default `volumes` changed from `"/tmp/rustfs"` to `"/var/lib/rustfs"` (persistent storage)
93+
- Console now defaults to localhost-only binding (`127.0.0.1:9001`)
94+
- Improved logging output to separate stdout and stderr streams
95+
- Enhanced documentation with security focus
96+
- Updated examples to demonstrate secure configurations
97+
- Service now explicitly grants write access only to required directories
98+
99+
### Deprecated
100+
101+
- `accessKey` option (removed, use `accessKeyFile`)
102+
- `secretKey` option (removed, use `secretKeyFile`)
103+
104+
### Removed
105+
106+
- Direct secret configuration options (must use file-based secrets)
107+
108+
### Fixed
109+
110+
- Secrets no longer stored in Nix store (world-readable)
111+
- Secrets no longer passed via environment variables
112+
- Service can no longer access user home directories
113+
- Service can no longer modify system files outside designated paths
114+
- Service cannot spawn arbitrary processes or modify system configuration
115+
- Console no longer exposed to public network by default
116+
117+
### Security
118+
119+
- Secrets are now passed via systemd LoadCredential (never in Nix store)
120+
- Service runs as unprivileged `rustfs` user (not root)
121+
- Comprehensive systemd sandboxing enabled
122+
- System calls restricted to safe subset
123+
- All capabilities dropped
124+
- Prevents privilege escalation
125+
- Memory execution protection
126+
- Network address family restrictions
127+
- Filesystem isolation with explicit write paths
128+
129+
## Migration Notes
130+
131+
Users upgrading from previous versions must:
132+
133+
1. Move secrets from `accessKey`/`secretKey` to file-based configuration
134+
2. Update to use `accessKeyFile` and `secretKeyFile` options
135+
3. Consider using sops-nix or agenix for secret management
136+
4. Review firewall rules (console now localhost-only by default)
137+
5. Update volume paths from `/tmp` to persistent storage
138+
139+
See [docs/MIGRATION.md](./docs/MIGRATION.md) for detailed migration instructions.
140+
141+
## Version Compatibility
142+
143+
- **NixOS**: 23.11 or later recommended
144+
- **Systemd**: 252 or later (for all security features)
145+
- **RustFS**: Compatible with current RustFS binary
146+
147+
## References
148+
149+
- [Issue #9](https://github.com/rustfs/rustfs-flake/issues/9) - Original security concerns
150+
- [docs/SECURITY.md](./docs/SECURITY.md) - Complete security documentation
151+
- [docs/MIGRATION.md](./docs/MIGRATION.md) - Migration guide
152+
- [docs/IMPROVEMENTS.md](./docs/IMPROVEMENTS.md) - Technical implementation details
153+

0 commit comments

Comments
 (0)