feat: web-arm install atticd

This commit is contained in:
2025-10-14 19:14:46 +02:00
parent e0568ddfdc
commit 742d0172cf
2 changed files with 208 additions and 0 deletions

View File

@@ -19,6 +19,7 @@
./modules/victoriametrics.nix ./modules/victoriametrics.nix
./modules/blackbox-exporter.nix ./modules/blackbox-exporter.nix
./modules/updns.nix ./modules/updns.nix
./modules/atticd.nix
./utils/modules/autoupgrade.nix ./utils/modules/autoupgrade.nix
./utils/modules/promtail ./utils/modules/promtail

View File

@@ -0,0 +1,207 @@
{ config, lib, pkgs, ... }:
let
atticHost = "attic.cloonar.com";
atticPort = 8080; # Internal port for atticd
in {
# Declare required secrets
sops.secrets.atticd = {
# This should contain environment variables for atticd
# Format: KEY=value per line
# Required:
# ATTIC_SERVER_TOKEN_HS256_SECRET=<random-256-bit-secret>
# Optional:
# ATTIC_SERVER_DATABASE_URL=postgresql://user:pass@localhost/attic
};
# Attic server service
services.atticd = {
enable = true;
# Credentials file from sops
environmentFile = config.sops.secrets.atticd.path;
settings = {
listen = "127.0.0.1:${toString atticPort}";
# API endpoint configuration
api-endpoint = "https://${atticHost}/";
# Allow automatic registration (set to false for production if you want to control access)
allow-registration = false;
# Require tokens for all operations
require-proof-of-possession = true;
# Chunking settings for large uploads
chunking = {
# Minimum chunk size: 16 MiB
min-size = 16 * 1024 * 1024;
# Average chunk size: 64 MiB
avg-size = 64 * 1024 * 1024;
# Maximum chunk size: 256 MiB
max-size = 256 * 1024 * 1024;
};
# Garbage collection
garbage-collection = {
# GC interval in seconds (12 hours)
interval = 12 * 60 * 60;
# Delete unreferenced chunks after 7 days
default-retention-period = 7 * 24 * 60 * 60;
};
# Storage configuration
storage = {
# Use local filesystem storage
type = "local";
# Store in /var/lib/atticd
path = "/var/lib/atticd/storage";
};
# Optional: S3-compatible storage (commented out)
# storage = {
# type = "s3";
# region = "eu-central-1";
# bucket = "attic-cache";
# endpoint = "https://s3.eu-central-1.amazonaws.com";
# };
# Database configuration
database = {
url = "postgresql://atticd@/atticd?host=/run/postgresql";
};
# Compression
compression = {
# Use zstd compression
type = "zstd";
level = 3; # Balance between speed and compression
};
};
};
# Create state directory with proper permissions
systemd.services.atticd = {
serviceConfig = {
StateDirectory = "atticd";
StateDirectoryMode = "0750";
# Security hardening
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
NoNewPrivileges = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
LockPersonality = true;
ProtectProc = "invisible";
ProtectClock = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectHostname = true;
SystemCallFilter = "@system-service";
SystemCallErrorNumber = "EPERM";
# Resource limits
LimitNOFILE = 65536;
};
};
# Nginx reverse proxy configuration
services.nginx.virtualHosts."${atticHost}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString atticPort}";
proxyWebsockets = true;
extraConfig = ''
# Increase timeouts for large uploads
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
# Increase body size limit for large NAR uploads (500MB)
client_max_body_size 500M;
client_body_buffer_size 128k;
# Proxy headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Buffering settings for better performance
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
proxy_temp_file_write_size 8k;
# Cache settings for static content
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
'';
};
# Health check endpoint
locations."/health" = {
proxyPass = "http://127.0.0.1:${toString atticPort}/health";
};
# API endpoint with stricter rate limiting
locations."~ ^/api/" = {
proxyPass = "http://127.0.0.1:${toString atticPort}";
extraConfig = ''
# Rate limiting for API endpoints
limit_req zone=attic_api burst=10 nodelay;
# Same proxy settings as above
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 500M;
'';
};
};
# Configure Nginx rate limiting zones
services.nginx.appendHttpConfig = ''
# Rate limiting zones for Attic
limit_req_zone $binary_remote_addr zone=attic_api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=attic_upload:10m rate=5r/s;
# Connection limiting
limit_conn_zone $binary_remote_addr zone=attic_conn:10m;
'';
services.postgresql.ensureUsers = [
{
name = "atticd";
ensureDBOwnership = true;
}
];
services.postgresql.ensureDatabases = [ "atticd" ];
services.postgresqlBackup.databases = [ "atticd" ];
services.borgbackup.jobs.default.exclude = [
"/var/lib/atticd"
];
# Monitoring with Prometheus (if you have it set up)
# services.prometheus.scrapeConfigs = [{
# job_name = "atticd";
# static_configs = [{
# targets = [ "127.0.0.1:${toString atticPort}" ];
# }];
# }];
}