Single Node Deployment¶
This guide covers deploying Hafiz on a single server. This is ideal for:
- Development and testing environments
- Small-scale production (< 1TB storage)
- Proof of concept deployments
- Learning and evaluation
Table of Contents¶
- Architecture Overview
- System Requirements
- Quick Start
- Installation Methods
- Binary Installation
- Docker Installation
- systemd Service
- Configuration
- TLS/HTTPS Setup
- Verification
- Client Configuration
- Maintenance
- Upgrading
- Troubleshooting
Architecture Overview¶
┌─────────────────────────────────────────────────────────────┐
│ Single Node Hafiz │
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Hafiz Server ││
│ │ ││
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ││
│ │ │ S3 API │ │ Admin API │ │ Admin Panel │ ││
│ │ │ Port 9000 │ │ /api/v1 │ │ /admin │ ││
│ │ └──────────────┘ └──────────────┘ └──────────────┘ ││
│ │ ││
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ││
│ │ │ Storage │ │ Metadata │ │ Auth │ ││
│ │ │ (Local FS) │ │ (SQLite) │ │ (Built-in) │ ││
│ │ └──────────────┘ └──────────────┘ └──────────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ Data Directory: /opt/hafiz/data │
│ - objects/ (S3 objects) │
│ - hafiz.db (SQLite metadata) │
│ - temp/ (Multipart uploads) │
└─────────────────────────────────────────────────────────────┘
System Requirements¶
Minimum Requirements¶
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 2 GB | 8+ GB |
| Storage | 20 GB | Based on data needs |
| OS | Linux (kernel 4.x+) | Rocky Linux 9 / Ubuntu 22.04 |
Supported Operating Systems¶
- Rocky Linux 8/9 (RHEL compatible)
- Ubuntu 20.04 / 22.04 / 24.04
- Debian 11 / 12
- Amazon Linux 2023
- Any Linux with glibc 2.17+
Network Requirements¶
| Port | Protocol | Purpose |
|---|---|---|
| 9000 | TCP | S3 API, Admin Panel, Admin API |
Quick Start¶
Option 1: One-Line Install (Linux)¶
Option 2: Docker (Fastest)¶
Option 3: Manual Binary¶
# Download latest release
curl -LO https://github.com/shellnoq/hafiz/releases/latest/download/hafiz-server-linux-amd64
chmod +x hafiz-server-linux-amd64
mv hafiz-server-linux-amd64 /usr/local/bin/hafiz-server
# Create data directory
mkdir -p /opt/hafiz/data
# Run
HAFIZ_DATA_DIR=/opt/hafiz/data hafiz-server
Installation Methods¶
Binary Installation¶
Step 1: Download Binary¶
# Set version
VERSION="0.1.0"
# Download
curl -LO "https://github.com/shellnoq/hafiz/releases/download/v${VERSION}/hafiz-server-linux-amd64"
# Make executable
chmod +x hafiz-server-linux-amd64
# Move to system path
sudo mv hafiz-server-linux-amd64 /usr/local/bin/hafiz-server
# Verify
hafiz-server --version
Step 2: Create Directories¶
# Create base directory
sudo mkdir -p /opt/hafiz/{data,logs,certs}
# Set ownership (replace 'hafiz' with your user)
sudo useradd -r -s /bin/false hafiz
sudo chown -R hafiz:hafiz /opt/hafiz
Step 3: Create Configuration¶
sudo tee /opt/hafiz/data/hafiz.toml << 'EOF'
[server]
bind_address = "0.0.0.0"
port = 9000
admin_port = 9001
workers = 0 # Auto-detect CPU count
max_connections = 10000
request_timeout_secs = 300
[storage]
data_dir = "/opt/hafiz/data"
temp_dir = "/tmp/hafiz"
max_object_size = 5497558138880 # 5 TiB
[database]
url = "sqlite:///opt/hafiz/data/hafiz.db?mode=rwc"
max_connections = 100
min_connections = 5
[auth]
enabled = true
root_access_key = "hafizadmin"
root_secret_key = "hafizadmin"
[logging]
level = "info"
format = "pretty"
[tls]
enabled = false
# Uncomment for HTTPS:
# enabled = true
# cert_file = "/opt/hafiz/certs/server.crt"
# key_file = "/opt/hafiz/certs/server.key"
[cluster]
enabled = false
EOF
Step 4: Run Manually (Testing)¶
Docker Installation¶
Basic Docker Run¶
docker run -d \
--name hafiz \
--restart unless-stopped \
-p 9000:9000 \
-v /opt/hafiz/data:/data \
-e HAFIZ_ROOT_ACCESS_KEY=hafizadmin \
-e HAFIZ_ROOT_SECRET_KEY=hafizadmin \
ghcr.io/shellnoq/hafiz:latest
Docker Compose¶
Create docker-compose.yml:
version: '3.8'
services:
hafiz:
image: ghcr.io/shellnoq/hafiz:latest
container_name: hafiz
restart: unless-stopped
ports:
- "9000:9000"
volumes:
- ./data:/data
- ./certs:/certs:ro # For TLS
environment:
- HAFIZ_DATA_DIR=/data
- HAFIZ_DATABASE_URL=sqlite:///data/hafiz.db?mode=rwc
- HAFIZ_ROOT_ACCESS_KEY=hafizadmin
- HAFIZ_ROOT_SECRET_KEY=hafizadmin
- HAFIZ_LOG_LEVEL=info
# Uncomment for HTTPS:
# - HAFIZ_TLS_CERT=/certs/server.crt
# - HAFIZ_TLS_KEY=/certs/server.key
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
volumes:
data:
systemd Service¶
Create Service File¶
sudo tee /etc/systemd/system/hafiz.service << 'EOF'
[Unit]
Description=Hafiz S3-Compatible Object Storage Server
Documentation=https://github.com/shellnoq/hafiz
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=hafiz
Group=hafiz
Environment="HAFIZ_CONFIG_FILE=/opt/hafiz/data/hafiz.toml"
ExecStart=/usr/local/bin/hafiz-server
Restart=always
RestartSec=5
LimitNOFILE=65536
WorkingDirectory=/opt/hafiz
# Security hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/opt/hafiz/data /opt/hafiz/logs
[Install]
WantedBy=multi-user.target
EOF
Enable and Start¶
# Reload systemd
sudo systemctl daemon-reload
# Enable on boot
sudo systemctl enable hafiz
# Start service
sudo systemctl start hafiz
# Check status
sudo systemctl status hafiz
# View logs
sudo journalctl -u hafiz -f
Configuration¶
Environment Variables¶
| Variable | Default | Description |
|---|---|---|
HAFIZ_DATA_DIR |
/data |
Data storage directory |
HAFIZ_DATABASE_URL |
SQLite | Database connection string |
HAFIZ_ROOT_ACCESS_KEY |
hafizadmin |
Root user access key |
HAFIZ_ROOT_SECRET_KEY |
hafizadmin |
Root user secret key |
HAFIZ_PORT |
9000 |
S3 API port |
HAFIZ_LOG_LEVEL |
info |
Log level (trace/debug/info/warn/error) |
HAFIZ_TLS_CERT |
- | TLS certificate path |
HAFIZ_TLS_KEY |
- | TLS private key path |
HAFIZ_CONFIG_FILE |
- | Configuration file path |
Configuration File Options¶
See Configuration Guide for complete reference.
TLS/HTTPS Setup¶
For secure communication, enable TLS:
Generate Self-Signed Certificate (Development)¶
# Create certificate directory
mkdir -p /opt/hafiz/certs
# Generate private key and certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /opt/hafiz/certs/server.key \
-out /opt/hafiz/certs/server.crt \
-subj "/CN=hafiz.local/O=Hafiz" \
-addext "subjectAltName=DNS:hafiz.local,DNS:localhost,IP:127.0.0.1"
# Set permissions
chmod 600 /opt/hafiz/certs/server.key
chown hafiz:hafiz /opt/hafiz/certs/*
Let's Encrypt Certificate (Production)¶
# Install certbot
sudo dnf install -y certbot # Rocky/RHEL
# or: sudo apt install -y certbot # Ubuntu/Debian
# Obtain certificate (HTTP challenge)
sudo certbot certonly --standalone \
-d your-domain.com \
--agree-tos \
--email your-email@example.com
# Copy certificates
sudo cp /etc/letsencrypt/live/your-domain.com/fullchain.pem /opt/hafiz/certs/server.crt
sudo cp /etc/letsencrypt/live/your-domain.com/privkey.pem /opt/hafiz/certs/server.key
sudo chown hafiz:hafiz /opt/hafiz/certs/*
# Set up auto-renewal
echo "0 0 1 * * root certbot renew --quiet && systemctl reload hafiz" | sudo tee /etc/cron.d/hafiz-cert-renewal
Enable TLS¶
Update configuration:
# Using environment variables
export HAFIZ_TLS_CERT=/opt/hafiz/certs/server.crt
export HAFIZ_TLS_KEY=/opt/hafiz/certs/server.key
# Or in hafiz.toml
[tls]
enabled = true
cert_file = "/opt/hafiz/certs/server.crt"
key_file = "/opt/hafiz/certs/server.key"
min_version = "1.2"
hsts_enabled = true
Restart the service:
Verification¶
Health Check¶
# HTTP
curl http://localhost:9000/health
# HTTPS (with self-signed cert)
curl -k https://localhost:9000/health
# HTTPS (with CA cert)
curl --cacert /opt/hafiz/certs/ca.crt https://localhost:9000/health
Expected response: ok
Admin Panel¶
Open in browser:
- HTTP: http://your-server:9000/admin
- HTTPS: https://your-server:9000/admin
S3 API Test¶
# Create bucket
curl -X PUT http://localhost:9000/test-bucket
# Upload object
echo "Hello World" | curl -X PUT -T - http://localhost:9000/test-bucket/hello.txt
# Download object
curl http://localhost:9000/test-bucket/hello.txt
# List objects
curl http://localhost:9000/test-bucket
Client Configuration¶
AWS CLI¶
# Configure profile
aws configure --profile hafiz
# Access Key ID: hafizadmin
# Secret Access Key: hafizadmin
# Default region: us-east-1
# Output format: json
# Usage
aws --endpoint-url http://localhost:9000 --profile hafiz s3 ls
aws --endpoint-url http://localhost:9000 --profile hafiz s3 mb s3://my-bucket
aws --endpoint-url http://localhost:9000 --profile hafiz s3 cp file.txt s3://my-bucket/
Environment Variables¶
export AWS_ACCESS_KEY_ID=hafizadmin
export AWS_SECRET_ACCESS_KEY=hafizadmin
export AWS_ENDPOINT_URL=http://localhost:9000
# Now use aws commands without --endpoint-url
aws s3 ls
Python (boto3)¶
import boto3
s3 = boto3.client(
's3',
endpoint_url='http://localhost:9000',
aws_access_key_id='hafizadmin',
aws_secret_access_key='hafizadmin'
)
# Create bucket
s3.create_bucket(Bucket='my-bucket')
# Upload file
s3.upload_file('local-file.txt', 'my-bucket', 'remote-file.txt')
# List objects
for obj in s3.list_objects_v2(Bucket='my-bucket').get('Contents', []):
print(obj['Key'])
Maintenance¶
Backup¶
# Stop service (for consistent backup)
sudo systemctl stop hafiz
# Backup data directory
tar -czvf hafiz-backup-$(date +%Y%m%d).tar.gz /opt/hafiz/data
# Restart service
sudo systemctl start hafiz
Restore¶
# Stop service
sudo systemctl stop hafiz
# Restore backup
tar -xzvf hafiz-backup-20240115.tar.gz -C /
# Start service
sudo systemctl start hafiz
Log Rotation¶
sudo tee /etc/logrotate.d/hafiz << 'EOF'
/opt/hafiz/logs/*.log {
daily
rotate 14
compress
delaycompress
notifempty
missingok
create 0640 hafiz hafiz
postrotate
systemctl reload hafiz > /dev/null 2>&1 || true
endscript
}
EOF
Upgrading¶
Binary Upgrade¶
# Download new version
curl -LO https://github.com/shellnoq/hafiz/releases/latest/download/hafiz-server-linux-amd64
# Stop service
sudo systemctl stop hafiz
# Backup current binary
sudo mv /usr/local/bin/hafiz-server /usr/local/bin/hafiz-server.bak
# Install new binary
sudo mv hafiz-server-linux-amd64 /usr/local/bin/hafiz-server
sudo chmod +x /usr/local/bin/hafiz-server
# Start service
sudo systemctl start hafiz
# Verify
hafiz-server --version
curl http://localhost:9000/health
Docker Upgrade¶
# Pull new image
docker pull ghcr.io/shellnoq/hafiz:latest
# Stop and remove old container
docker stop hafiz
docker rm hafiz
# Start with new image
docker run -d \
--name hafiz \
--restart unless-stopped \
-p 9000:9000 \
-v hafiz-data:/data \
ghcr.io/shellnoq/hafiz:latest
Troubleshooting¶
Common Issues¶
| Issue | Solution |
|---|---|
| Permission denied | Check file ownership: chown -R hafiz:hafiz /opt/hafiz |
| Port already in use | Check: ss -tlnp | grep 9000 |
| Database locked | Ensure only one instance is running |
| TLS handshake failed | Verify certificate paths and permissions |
| Out of disk space | Check: df -h /opt/hafiz/data |
Debug Logging¶
# Enable debug logging
HAFIZ_LOG_LEVEL=debug hafiz-server
# Or in systemd
sudo systemctl edit hafiz
# Add: Environment="HAFIZ_LOG_LEVEL=debug"
sudo systemctl restart hafiz
Check Service Status¶
# Service status
sudo systemctl status hafiz
# Recent logs
sudo journalctl -u hafiz --since "10 minutes ago"
# Follow logs
sudo journalctl -u hafiz -f
Network Troubleshooting¶
# Check if port is listening
ss -tlnp | grep 9000
# Test local connection
curl -v http://localhost:9000/health
# Test from another machine
curl -v http://your-server:9000/health
# Check firewall
sudo firewall-cmd --list-ports # RHEL/Rocky
sudo ufw status # Ubuntu
Next Steps¶
- Configure TLS/HTTPS for secure communication
- Set up Multi-Node Cluster for high availability
- Configure External Integrations (Nextcloud, etc.)
- Enable Monitoring with Prometheus