Add Podman deployment support for HMAC File Server 3.2
- Introduced Dockerfile.podman for building a Podman-compatible image. - Created deploy-podman.sh script for automated deployment and management. - Added Podman-specific README.md with quick start and configuration details. - Included example configuration file (config.toml.example) for production settings. - Implemented systemd service file for managing the HMAC File Server as a service. - Established health checks and security features in the container setup. - Documented deployment commands and troubleshooting steps in README.md.
This commit is contained in:
71
dockerenv/podman/Dockerfile.podman
Normal file
71
dockerenv/podman/Dockerfile.podman
Normal file
@ -0,0 +1,71 @@
|
||||
# Dockerfile.podman - Optimized for Podman deployment
|
||||
# HMAC File Server 3.2 "Tremora del Terra" - Podman Edition
|
||||
|
||||
FROM docker.io/golang:1.24-alpine AS builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache git ca-certificates tzdata
|
||||
|
||||
# Copy source code
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
|
||||
# Build static binary optimized for containers
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build \
|
||||
-ldflags="-w -s -extldflags '-static'" \
|
||||
-a -installsuffix cgo \
|
||||
-o hmac-file-server ./cmd/server/
|
||||
|
||||
# Production stage - Alpine for better compatibility and security
|
||||
FROM alpine:latest
|
||||
|
||||
# Install runtime dependencies and create user
|
||||
RUN apk add --no-cache \
|
||||
ca-certificates \
|
||||
tzdata \
|
||||
curl \
|
||||
shadow \
|
||||
&& adduser -D -s /bin/sh -u 1011 appuser \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Create application directories with proper ownership
|
||||
RUN mkdir -p /app /data /deduplication /iso /logs /tmp && \
|
||||
chown -R appuser:appuser /app /data /deduplication /iso /logs /tmp && \
|
||||
chmod 755 /app /data /deduplication /iso /logs && \
|
||||
chmod 1777 /tmp
|
||||
|
||||
# Copy binary from builder stage
|
||||
COPY --from=builder /build/hmac-file-server /app/hmac-file-server
|
||||
|
||||
# Set proper permissions on binary
|
||||
RUN chmod +x /app/hmac-file-server && \
|
||||
chown appuser:appuser /app/hmac-file-server
|
||||
|
||||
# Switch to non-root user for security
|
||||
USER appuser
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Add labels for better container management
|
||||
LABEL org.opencontainers.image.title="HMAC File Server" \
|
||||
org.opencontainers.image.description="Secure file server with XEP-0363 support" \
|
||||
org.opencontainers.image.version="3.2" \
|
||||
org.opencontainers.image.vendor="PlusOne" \
|
||||
org.opencontainers.image.source="https://github.com/PlusOne/hmac-file-server" \
|
||||
org.opencontainers.image.licenses="MIT"
|
||||
|
||||
# Health check for container orchestration
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
||||
CMD curl -f http://localhost:8888/health || exit 1
|
||||
|
||||
# Expose default port (configurable via config)
|
||||
EXPOSE 8888
|
||||
|
||||
# Use exec form for proper signal handling
|
||||
ENTRYPOINT ["/app/hmac-file-server"]
|
||||
CMD ["-config", "/app/config.toml"]
|
263
dockerenv/podman/README.md
Normal file
263
dockerenv/podman/README.md
Normal file
@ -0,0 +1,263 @@
|
||||
# HMAC File Server - Podman Configuration Examples
|
||||
|
||||
This directory contains Podman-specific deployment files for HMAC File Server 3.2 "Tremora del Terra".
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://github.com/PlusOne/hmac-file-server.git
|
||||
cd hmac-file-server/dockerenv/podman
|
||||
|
||||
# Deploy with single command
|
||||
./deploy-podman.sh
|
||||
|
||||
# Check status
|
||||
./deploy-podman.sh status
|
||||
|
||||
# View logs
|
||||
./deploy-podman.sh logs
|
||||
```
|
||||
|
||||
## 📁 Files Overview
|
||||
|
||||
### `Dockerfile.podman`
|
||||
- **Purpose**: Optimized Dockerfile for Podman deployment
|
||||
- **Features**:
|
||||
- Security-hardened Alpine-based image
|
||||
- Non-root user (UID 1011)
|
||||
- Health checks included
|
||||
- Static binary compilation
|
||||
- Minimal attack surface
|
||||
|
||||
### `deploy-podman.sh`
|
||||
- **Purpose**: Complete deployment automation script
|
||||
- **Features**:
|
||||
- Interactive deployment with colored output
|
||||
- Automatic configuration generation with random secrets
|
||||
- Security-hardened container settings
|
||||
- Pod management for XMPP integration
|
||||
- Health monitoring and status reporting
|
||||
|
||||
### `hmac-file-server.service`
|
||||
- **Purpose**: Systemd service unit for service management
|
||||
- **Usage**: Place in `~/.config/systemd/user/` (rootless) or `/etc/systemd/system/` (system-wide)
|
||||
|
||||
## 🛠️ Deployment Commands
|
||||
|
||||
### Basic Deployment
|
||||
```bash
|
||||
# Full deployment (directories, config, build, start)
|
||||
./deploy-podman.sh deploy
|
||||
|
||||
# Start services only
|
||||
./deploy-podman.sh start
|
||||
|
||||
# Stop all services
|
||||
./deploy-podman.sh stop
|
||||
|
||||
# Restart services
|
||||
./deploy-podman.sh restart
|
||||
```
|
||||
|
||||
### Management Commands
|
||||
```bash
|
||||
# Check status and health
|
||||
./deploy-podman.sh status
|
||||
|
||||
# View real-time logs
|
||||
./deploy-podman.sh logs
|
||||
|
||||
# Show current configuration
|
||||
./deploy-podman.sh config
|
||||
|
||||
# Build image only
|
||||
./deploy-podman.sh build
|
||||
|
||||
# Create networking pod only
|
||||
./deploy-podman.sh pod
|
||||
|
||||
# Complete cleanup (keeps data)
|
||||
./deploy-podman.sh clean
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Environment Variables
|
||||
```bash
|
||||
# Custom data directory
|
||||
export APP_DATA="/custom/path/hmac-file-server"
|
||||
|
||||
# Custom ports
|
||||
export LISTEN_PORT="9999"
|
||||
export METRICS_PORT="9998"
|
||||
|
||||
# Deploy with custom settings
|
||||
./deploy-podman.sh
|
||||
```
|
||||
|
||||
### Generated Configuration
|
||||
The deployment script generates a production-ready configuration with:
|
||||
- ✅ **XMPP-compatible file extensions**
|
||||
- ✅ **Random HMAC and JWT secrets**
|
||||
- ✅ **Optimized performance settings**
|
||||
- ✅ **Security hardening enabled**
|
||||
- ✅ **Comprehensive logging**
|
||||
|
||||
## 🔒 Security Features
|
||||
|
||||
### Container Security
|
||||
- **Rootless operation**: Runs as non-root user (UID 1011)
|
||||
- **Capability dropping**: `--cap-drop=ALL`
|
||||
- **No new privileges**: `--security-opt no-new-privileges`
|
||||
- **Read-only filesystem**: `--read-only` with tmpfs for /tmp
|
||||
- **SELinux labels**: Volume mounts with `:Z` labels
|
||||
|
||||
### Network Security
|
||||
- **Pod isolation**: Containers run in isolated pods
|
||||
- **Port binding**: Only necessary ports exposed
|
||||
- **Health monitoring**: Built-in health checks
|
||||
|
||||
## 🔄 Systemd Integration
|
||||
|
||||
### User Service (Rootless - Recommended)
|
||||
```bash
|
||||
# Copy service file
|
||||
cp hmac-file-server.service ~/.config/systemd/user/
|
||||
|
||||
# Enable and start
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable hmac-file-server.service
|
||||
systemctl --user start hmac-file-server.service
|
||||
|
||||
# Check status
|
||||
systemctl --user status hmac-file-server.service
|
||||
```
|
||||
|
||||
### System Service (Root)
|
||||
```bash
|
||||
# Copy service file
|
||||
sudo cp hmac-file-server.service /etc/systemd/system/
|
||||
|
||||
# Enable and start
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable hmac-file-server.service
|
||||
sudo systemctl start hmac-file-server.service
|
||||
|
||||
# Check status
|
||||
sudo systemctl status hmac-file-server.service
|
||||
```
|
||||
|
||||
## 🎯 XMPP Integration
|
||||
|
||||
### Pod-based XMPP Deployment
|
||||
```bash
|
||||
# Create XMPP services pod
|
||||
podman pod create --name xmpp-services \
|
||||
--publish 5222:5222 \
|
||||
--publish 5269:5269 \
|
||||
--publish 5443:5443 \
|
||||
--publish 8888:8888
|
||||
|
||||
# Add Prosody XMPP server
|
||||
podman run -d --pod xmpp-services --name prosody \
|
||||
-v ./prosody-config:/etc/prosody:ro \
|
||||
-v ./prosody-data:/var/lib/prosody:rw \
|
||||
docker.io/prosody/prosody:latest
|
||||
|
||||
# Add HMAC File Server
|
||||
podman run -d --pod xmpp-services --name hmac-file-server \
|
||||
-v ./config.toml:/app/config.toml:ro \
|
||||
-v ./data:/data:rw \
|
||||
localhost/hmac-file-server:latest -config /app/config.toml
|
||||
```
|
||||
|
||||
## 📊 Monitoring and Health
|
||||
|
||||
### Health Checks
|
||||
```bash
|
||||
# Manual health check
|
||||
curl -f http://localhost:8888/health
|
||||
|
||||
# Container health status
|
||||
podman healthcheck run hmac-file-server
|
||||
|
||||
# Continuous monitoring
|
||||
watch -n 5 'curl -s http://localhost:8888/health && echo " - $(date)"'
|
||||
```
|
||||
|
||||
### Metrics
|
||||
```bash
|
||||
# Prometheus metrics
|
||||
curl http://localhost:9090/metrics
|
||||
|
||||
# Pod statistics
|
||||
podman pod stats xmpp-pod
|
||||
|
||||
# Container logs
|
||||
podman logs -f hmac-file-server
|
||||
```
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Permission Errors
|
||||
```bash
|
||||
# Fix SELinux contexts
|
||||
restorecon -R /opt/podman/hmac-file-server
|
||||
|
||||
# Check volume permissions
|
||||
podman unshare ls -la /opt/podman/hmac-file-server
|
||||
```
|
||||
|
||||
#### Container Won't Start
|
||||
```bash
|
||||
# Check image exists
|
||||
podman images | grep hmac-file-server
|
||||
|
||||
# Validate configuration
|
||||
./deploy-podman.sh config
|
||||
|
||||
# Debug with interactive container
|
||||
podman run -it --rm localhost/hmac-file-server:latest /bin/sh
|
||||
```
|
||||
|
||||
#### Network Issues
|
||||
```bash
|
||||
# Check pod networking
|
||||
podman pod ps
|
||||
podman port hmac-file-server
|
||||
|
||||
# Test connectivity
|
||||
nc -zv localhost 8888
|
||||
```
|
||||
|
||||
### Log Analysis
|
||||
```bash
|
||||
# Container logs
|
||||
podman logs hmac-file-server
|
||||
|
||||
# Application logs
|
||||
tail -f /opt/podman/hmac-file-server/logs/hmac-file-server.log
|
||||
|
||||
# System journal
|
||||
journalctl --user -u hmac-file-server.service -f
|
||||
```
|
||||
|
||||
## 🎉 Success Verification
|
||||
|
||||
After deployment, verify everything works:
|
||||
|
||||
1. **Health Check**: `curl -f http://localhost:8888/health`
|
||||
2. **Metrics**: `curl http://localhost:9090/metrics`
|
||||
3. **Container Status**: `podman ps`
|
||||
4. **Pod Status**: `podman pod ps`
|
||||
5. **Logs**: `./deploy-podman.sh logs`
|
||||
|
||||
## 📚 Additional Resources
|
||||
|
||||
- [Podman Official Documentation](https://docs.podman.io/)
|
||||
- [HMAC File Server GitHub](https://github.com/PlusOne/hmac-file-server)
|
||||
- [XEP-0363 Specification](https://xmpp.org/extensions/xep-0363.html)
|
||||
- [Container Security Best Practices](https://docs.podman.io/en/latest/markdown/podman-run.1.html#security-options)
|
102
dockerenv/podman/config.toml.example
Normal file
102
dockerenv/podman/config.toml.example
Normal file
@ -0,0 +1,102 @@
|
||||
# HMAC File Server - Podman Production Configuration
|
||||
# This file is auto-generated by deploy-podman.sh
|
||||
# Edit as needed for your specific deployment requirements
|
||||
|
||||
[server]
|
||||
listen_address = "8888"
|
||||
storage_path = "/data"
|
||||
metrics_enabled = true
|
||||
metrics_port = "9090"
|
||||
max_upload_size = "10GB"
|
||||
max_header_bytes = 1048576
|
||||
cleanup_interval = "24h"
|
||||
max_file_age = "720h"
|
||||
enable_dynamic_workers = true
|
||||
worker_scale_up_thresh = 40
|
||||
worker_scale_down_thresh = 10
|
||||
deduplication_enabled = true
|
||||
min_free_bytes = "1GB"
|
||||
file_naming = "original"
|
||||
|
||||
# Network resilience settings
|
||||
graceful_shutdown_timeout = "300s"
|
||||
connection_drain_timeout = "120s"
|
||||
max_idle_conns_per_host = 5
|
||||
idle_conn_timeout = "90s"
|
||||
disable_keep_alives = false
|
||||
client_timeout = "300s"
|
||||
restart_grace_period = "60s"
|
||||
|
||||
[uploads]
|
||||
# XMPP-compatible file extensions for maximum client support
|
||||
allowed_extensions = [".zip", ".rar", ".7z", ".tar.gz", ".tgz", ".gpg", ".enc", ".pgp", ".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp", ".wav", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".mpeg", ".mpg", ".m4v", ".3gp", ".3g2", ".mp3", ".ogg", ".doc", ".docx"]
|
||||
chunked_uploads_enabled = true
|
||||
chunk_size = "32MB"
|
||||
resumable_uploads_enabled = true
|
||||
max_resumable_age = "48h"
|
||||
sessiontimeout = "60m"
|
||||
maxretries = 3
|
||||
|
||||
# Upload resilience settings
|
||||
session_persistence = true
|
||||
session_recovery_timeout = "300s"
|
||||
client_reconnect_window = "120s"
|
||||
upload_slot_ttl = "3600s"
|
||||
retry_failed_uploads = true
|
||||
max_upload_retries = 3
|
||||
|
||||
[downloads]
|
||||
resumable_downloads_enabled = true
|
||||
chunked_downloads_enabled = true
|
||||
chunk_size = "32MB"
|
||||
# Same extensions as uploads for consistency
|
||||
allowed_extensions = [".zip", ".rar", ".7z", ".tar.gz", ".tgz", ".gpg", ".enc", ".pgp", ".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp", ".wav", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".mpeg", ".mpg", ".m4v", ".3gp", ".3g2", ".mp3", ".ogg", ".doc", ".docx"]
|
||||
|
||||
[security]
|
||||
# IMPORTANT: Change these secrets in production!
|
||||
secret = "CHANGE-THIS-PRODUCTION-SECRET-HMAC-KEY"
|
||||
enablejwt = true
|
||||
jwtsecret = "CHANGE-THIS-JWT-SECRET-KEY"
|
||||
jwtalgorithm = "HS256"
|
||||
jwtexpiration = "24h"
|
||||
|
||||
[logging]
|
||||
level = "info"
|
||||
file = "/logs/hmac-file-server.log"
|
||||
max_size = 100
|
||||
max_backups = 7
|
||||
max_age = 30
|
||||
compress = true
|
||||
|
||||
[deduplication]
|
||||
enabled = true
|
||||
directory = "/deduplication"
|
||||
|
||||
[workers]
|
||||
numworkers = 4
|
||||
uploadqueuesize = 100
|
||||
|
||||
[timeouts]
|
||||
readtimeout = "3600s"
|
||||
writetimeout = "3600s"
|
||||
idletimeout = "3600s"
|
||||
shutdown = "30s"
|
||||
|
||||
[versioning]
|
||||
enableversioning = false
|
||||
backend = "simple"
|
||||
maxversions = 1
|
||||
|
||||
[redis]
|
||||
redisenabled = false
|
||||
redisdbindex = 0
|
||||
redisaddr = "localhost:6379"
|
||||
redispassword = ""
|
||||
redishealthcheckinterval = "120s"
|
||||
|
||||
[clamav]
|
||||
clamavenabled = false
|
||||
clamavsocket = "/var/run/clamav/clamd.ctl"
|
||||
numscanworkers = 2
|
||||
scanfileextensions = [".exe", ".dll", ".bin", ".com", ".bat", ".sh", ".php", ".js"]
|
||||
maxscansize = "200MB"
|
390
dockerenv/podman/deploy-podman.sh
Executable file
390
dockerenv/podman/deploy-podman.sh
Executable file
@ -0,0 +1,390 @@
|
||||
#!/bin/bash
|
||||
# deploy-podman.sh - Production Podman deployment script for HMAC File Server 3.2
|
||||
# Usage: ./deploy-podman.sh [start|stop|restart|status|logs|config]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color codes for pretty output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Logging functions
|
||||
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
||||
warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
||||
error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# Configuration variables
|
||||
readonly APP_NAME='hmac-file-server'
|
||||
readonly POD_NAME='xmpp-pod'
|
||||
readonly CTR_NAME="${POD_NAME}-${APP_NAME}"
|
||||
readonly CTR_IMAGE='localhost/hmac-file-server:latest'
|
||||
readonly RESTART_POLICY='unless-stopped'
|
||||
readonly CTR_UID='1011'
|
||||
readonly APP_DATA="${APP_DATA:-/opt/podman/hmac-file-server}"
|
||||
readonly LISTEN_PORT="${LISTEN_PORT:-8888}"
|
||||
readonly METRICS_PORT="${METRICS_PORT:-9090}"
|
||||
readonly CONFIG_FILE="${APP_DATA}/config/config.toml"
|
||||
|
||||
# Check if running as root (not recommended for Podman)
|
||||
check_user() {
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
warning "Running as root. Consider using Podman rootless for better security."
|
||||
read -p "Continue anyway? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Create application directories
|
||||
setup_directories() {
|
||||
info "Setting up application directories..."
|
||||
|
||||
mkdir -p "${APP_DATA}"/{config,data,deduplication,logs}
|
||||
|
||||
# Set proper ownership
|
||||
if command -v podman >/dev/null 2>&1; then
|
||||
podman unshare chown -R "${CTR_UID}:${CTR_UID}" "${APP_DATA}"
|
||||
else
|
||||
error "Podman not found. Please install Podman first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
success "Directories created at ${APP_DATA}"
|
||||
}
|
||||
|
||||
# Generate configuration file
|
||||
generate_config() {
|
||||
if [[ -f "${CONFIG_FILE}" ]]; then
|
||||
warning "Configuration file already exists at ${CONFIG_FILE}"
|
||||
read -p "Overwrite? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
info "Generating configuration file..."
|
||||
|
||||
# Generate random secrets
|
||||
local hmac_secret=$(openssl rand -base64 32 2>/dev/null || head -c 32 /dev/urandom | base64)
|
||||
local jwt_secret=$(openssl rand -base64 32 2>/dev/null || head -c 32 /dev/urandom | base64)
|
||||
|
||||
cat > "${CONFIG_FILE}" << EOF
|
||||
# HMAC File Server 3.2 - Podman Production Configuration
|
||||
# Generated on $(date)
|
||||
|
||||
[server]
|
||||
listen_address = "${LISTEN_PORT}"
|
||||
storage_path = "/data"
|
||||
metrics_enabled = true
|
||||
metrics_port = "${METRICS_PORT}"
|
||||
max_upload_size = "10GB"
|
||||
max_header_bytes = 1048576
|
||||
cleanup_interval = "24h"
|
||||
max_file_age = "720h"
|
||||
enable_dynamic_workers = true
|
||||
worker_scale_up_thresh = 40
|
||||
worker_scale_down_thresh = 10
|
||||
deduplication_enabled = true
|
||||
min_free_bytes = "1GB"
|
||||
file_naming = "original"
|
||||
|
||||
[uploads]
|
||||
# XMPP-compatible file extensions for maximum client support
|
||||
allowed_extensions = [".zip", ".rar", ".7z", ".tar.gz", ".tgz", ".gpg", ".enc", ".pgp", ".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp", ".wav", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".mpeg", ".mpg", ".m4v", ".3gp", ".3g2", ".mp3", ".ogg", ".doc", ".docx"]
|
||||
chunked_uploads_enabled = true
|
||||
chunk_size = "32MB"
|
||||
resumable_uploads_enabled = true
|
||||
max_resumable_age = "48h"
|
||||
sessiontimeout = "60m"
|
||||
maxretries = 3
|
||||
|
||||
# Upload resilience settings
|
||||
session_persistence = true
|
||||
session_recovery_timeout = "300s"
|
||||
client_reconnect_window = "120s"
|
||||
upload_slot_ttl = "3600s"
|
||||
retry_failed_uploads = true
|
||||
max_upload_retries = 3
|
||||
|
||||
[downloads]
|
||||
resumable_downloads_enabled = true
|
||||
chunked_downloads_enabled = true
|
||||
chunk_size = "32MB"
|
||||
# Same extensions as uploads for consistency
|
||||
allowed_extensions = [".zip", ".rar", ".7z", ".tar.gz", ".tgz", ".gpg", ".enc", ".pgp", ".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp", ".wav", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".mpeg", ".mpg", ".m4v", ".3gp", ".3g2", ".mp3", ".ogg", ".doc", ".docx"]
|
||||
|
||||
[security]
|
||||
secret = "${hmac_secret}"
|
||||
enablejwt = true
|
||||
jwtsecret = "${jwt_secret}"
|
||||
jwtalgorithm = "HS256"
|
||||
jwtexpiration = "24h"
|
||||
|
||||
[logging]
|
||||
level = "info"
|
||||
file = "/logs/hmac-file-server.log"
|
||||
max_size = 100
|
||||
max_backups = 7
|
||||
max_age = 30
|
||||
compress = true
|
||||
|
||||
[deduplication]
|
||||
enabled = true
|
||||
directory = "/deduplication"
|
||||
|
||||
[workers]
|
||||
numworkers = 4
|
||||
uploadqueuesize = 100
|
||||
|
||||
[timeouts]
|
||||
readtimeout = "3600s"
|
||||
writetimeout = "3600s"
|
||||
idletimeout = "3600s"
|
||||
shutdown = "30s"
|
||||
EOF
|
||||
|
||||
success "Configuration generated at ${CONFIG_FILE}"
|
||||
warning "Secrets have been auto-generated. Keep this file secure!"
|
||||
}
|
||||
|
||||
# Build container image
|
||||
build_image() {
|
||||
info "Checking if image ${CTR_IMAGE} exists..."
|
||||
|
||||
if podman image exists "${CTR_IMAGE}"; then
|
||||
warning "Image ${CTR_IMAGE} already exists"
|
||||
read -p "Rebuild? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
info "Building container image ${CTR_IMAGE}..."
|
||||
|
||||
# Find the Dockerfile
|
||||
local dockerfile_path
|
||||
if [[ -f "dockerenv/podman/Dockerfile.podman" ]]; then
|
||||
dockerfile_path="dockerenv/podman/Dockerfile.podman"
|
||||
elif [[ -f "Dockerfile.podman" ]]; then
|
||||
dockerfile_path="Dockerfile.podman"
|
||||
else
|
||||
error "Dockerfile.podman not found. Please run from project root or ensure file exists."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
podman build --no-cache -t "${CTR_IMAGE}" -f "${dockerfile_path}" .
|
||||
|
||||
success "Image ${CTR_IMAGE} built successfully"
|
||||
}
|
||||
|
||||
# Create pod for networking
|
||||
create_pod() {
|
||||
info "Creating pod ${POD_NAME}..."
|
||||
|
||||
# Remove existing pod if it exists
|
||||
if podman pod exists "${POD_NAME}"; then
|
||||
warning "Pod ${POD_NAME} already exists, removing..."
|
||||
podman pod stop "${POD_NAME}" 2>/dev/null || true
|
||||
podman pod rm "${POD_NAME}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
podman pod create --name "${POD_NAME}" \
|
||||
--publish "${LISTEN_PORT}:8888" \
|
||||
--publish "${METRICS_PORT}:9090"
|
||||
|
||||
success "Pod ${POD_NAME} created"
|
||||
}
|
||||
|
||||
# Start the container
|
||||
start_container() {
|
||||
info "Starting HMAC File Server container..."
|
||||
|
||||
# Stop and remove existing container
|
||||
podman container stop "${CTR_NAME}" 2>/dev/null || true
|
||||
podman container rm "${CTR_NAME}" 2>/dev/null || true
|
||||
|
||||
# Run container with security-hardened settings
|
||||
podman run -d \
|
||||
--pod="${POD_NAME}" \
|
||||
--restart="${RESTART_POLICY}" \
|
||||
--name "${CTR_NAME}" \
|
||||
--user "${CTR_UID}:${CTR_UID}" \
|
||||
--cap-drop=ALL \
|
||||
--security-opt no-new-privileges \
|
||||
--read-only \
|
||||
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
|
||||
-v "${CONFIG_FILE}:/app/config.toml:ro,Z" \
|
||||
-v "${APP_DATA}/data:/data:rw,Z" \
|
||||
-v "${APP_DATA}/deduplication:/deduplication:rw,Z" \
|
||||
-v "${APP_DATA}/logs:/logs:rw,Z" \
|
||||
--health-cmd="curl -f http://localhost:8888/health || exit 1" \
|
||||
--health-interval=30s \
|
||||
--health-timeout=10s \
|
||||
--health-retries=3 \
|
||||
--health-start-period=40s \
|
||||
"${CTR_IMAGE}" -config /app/config.toml
|
||||
|
||||
success "Container ${CTR_NAME} started successfully!"
|
||||
}
|
||||
|
||||
# Stop the container
|
||||
stop_container() {
|
||||
info "Stopping HMAC File Server..."
|
||||
|
||||
podman container stop "${CTR_NAME}" 2>/dev/null || true
|
||||
podman container rm "${CTR_NAME}" 2>/dev/null || true
|
||||
podman pod stop "${POD_NAME}" 2>/dev/null || true
|
||||
podman pod rm "${POD_NAME}" 2>/dev/null || true
|
||||
|
||||
success "HMAC File Server stopped"
|
||||
}
|
||||
|
||||
# Show status
|
||||
show_status() {
|
||||
echo
|
||||
info "=== HMAC File Server Status ==="
|
||||
|
||||
if podman pod exists "${POD_NAME}"; then
|
||||
echo "Pod Status:"
|
||||
podman pod ps --filter "name=${POD_NAME}"
|
||||
echo
|
||||
fi
|
||||
|
||||
if podman container exists "${CTR_NAME}"; then
|
||||
echo "Container Status:"
|
||||
podman ps --filter "name=${CTR_NAME}"
|
||||
echo
|
||||
|
||||
echo "Health Status:"
|
||||
podman healthcheck run "${CTR_NAME}" 2>/dev/null && echo "✅ Healthy" || echo "❌ Unhealthy"
|
||||
echo
|
||||
else
|
||||
warning "Container ${CTR_NAME} not found"
|
||||
fi
|
||||
|
||||
echo "Service URLs:"
|
||||
echo " 🌐 File Server: http://localhost:${LISTEN_PORT}"
|
||||
echo " 📊 Metrics: http://localhost:${METRICS_PORT}/metrics"
|
||||
echo " 🔍 Health Check: http://localhost:${LISTEN_PORT}/health"
|
||||
echo
|
||||
}
|
||||
|
||||
# Show logs
|
||||
show_logs() {
|
||||
if podman container exists "${CTR_NAME}"; then
|
||||
info "Showing logs for ${CTR_NAME} (Ctrl+C to exit)..."
|
||||
podman logs -f "${CTR_NAME}"
|
||||
else
|
||||
error "Container ${CTR_NAME} not found"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Full deployment
|
||||
deploy() {
|
||||
info "Starting full HMAC File Server deployment..."
|
||||
|
||||
check_user
|
||||
setup_directories
|
||||
generate_config
|
||||
build_image
|
||||
create_pod
|
||||
start_container
|
||||
|
||||
sleep 5 # Wait for container to start
|
||||
show_status
|
||||
|
||||
success "🎉 HMAC File Server deployed successfully!"
|
||||
echo
|
||||
info "Next steps:"
|
||||
echo "1. Test the service: curl -f http://localhost:${LISTEN_PORT}/health"
|
||||
echo "2. View logs: ./deploy-podman.sh logs"
|
||||
echo "3. Check status: ./deploy-podman.sh status"
|
||||
echo "4. Edit config: ${CONFIG_FILE}"
|
||||
echo
|
||||
}
|
||||
|
||||
# Main command dispatcher
|
||||
case "${1:-deploy}" in
|
||||
start|deploy)
|
||||
deploy
|
||||
;;
|
||||
stop)
|
||||
stop_container
|
||||
;;
|
||||
restart)
|
||||
stop_container
|
||||
sleep 2
|
||||
create_pod
|
||||
start_container
|
||||
show_status
|
||||
;;
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
logs)
|
||||
show_logs
|
||||
;;
|
||||
config)
|
||||
info "Configuration file location: ${CONFIG_FILE}"
|
||||
if [[ -f "${CONFIG_FILE}" ]]; then
|
||||
echo "Current configuration:"
|
||||
cat "${CONFIG_FILE}"
|
||||
else
|
||||
warning "Configuration file not found. Run './deploy-podman.sh' to generate it."
|
||||
fi
|
||||
;;
|
||||
build)
|
||||
build_image
|
||||
;;
|
||||
pod)
|
||||
create_pod
|
||||
;;
|
||||
clean)
|
||||
warning "This will remove all containers, pods, and the image. Data will be preserved."
|
||||
read -p "Continue? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
stop_container
|
||||
podman image rm "${CTR_IMAGE}" 2>/dev/null || true
|
||||
success "Cleanup completed"
|
||||
fi
|
||||
;;
|
||||
help|--help|-h)
|
||||
echo "HMAC File Server Podman Deployment Script"
|
||||
echo
|
||||
echo "Usage: $0 [COMMAND]"
|
||||
echo
|
||||
echo "Commands:"
|
||||
echo " deploy Full deployment (default)"
|
||||
echo " start Start services"
|
||||
echo " stop Stop all services"
|
||||
echo " restart Restart services"
|
||||
echo " status Show service status"
|
||||
echo " logs Show container logs"
|
||||
echo " config Show configuration"
|
||||
echo " build Build container image only"
|
||||
echo " pod Create pod only"
|
||||
echo " clean Remove containers and image"
|
||||
echo " help Show this help"
|
||||
echo
|
||||
echo "Environment Variables:"
|
||||
echo " APP_DATA Data directory (default: /opt/podman/hmac-file-server)"
|
||||
echo " LISTEN_PORT Server port (default: 8888)"
|
||||
echo " METRICS_PORT Metrics port (default: 9090)"
|
||||
echo
|
||||
;;
|
||||
*)
|
||||
error "Unknown command: $1"
|
||||
echo "Run '$0 help' for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
55
dockerenv/podman/hmac-file-server.service
Normal file
55
dockerenv/podman/hmac-file-server.service
Normal file
@ -0,0 +1,55 @@
|
||||
# HMAC File Server - Podman Systemd Service
|
||||
# Place this file at: ~/.config/systemd/user/hmac-file-server.service
|
||||
# For system-wide: /etc/systemd/system/hmac-file-server.service
|
||||
|
||||
[Unit]
|
||||
Description=HMAC File Server 3.2 "Tremora del Terra" (Podman)
|
||||
Documentation=https://github.com/PlusOne/hmac-file-server
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
RequiresMountsFor=%t/containers
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
NotifyAccess=all
|
||||
Environment=PODMAN_SYSTEMD_UNIT=%n
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=70
|
||||
|
||||
# Main container execution
|
||||
ExecStart=/usr/bin/podman run \
|
||||
--cidfile=%t/%n.ctr-id \
|
||||
--cgroups=no-conmon \
|
||||
--rm \
|
||||
--sdnotify=conmon \
|
||||
--replace \
|
||||
--name hmac-file-server \
|
||||
--user 1011:1011 \
|
||||
--cap-drop=ALL \
|
||||
--security-opt no-new-privileges \
|
||||
--read-only \
|
||||
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
|
||||
--publish 8888:8888 \
|
||||
--publish 9090:9090 \
|
||||
--volume /opt/podman/hmac-file-server/config/config.toml:/app/config.toml:ro,Z \
|
||||
--volume /opt/podman/hmac-file-server/data:/data:rw,Z \
|
||||
--volume /opt/podman/hmac-file-server/deduplication:/deduplication:rw,Z \
|
||||
--volume /opt/podman/hmac-file-server/logs:/logs:rw,Z \
|
||||
--health-cmd="curl -f http://localhost:8888/health || exit 1" \
|
||||
--health-interval=30s \
|
||||
--health-timeout=10s \
|
||||
--health-retries=3 \
|
||||
--health-start-period=40s \
|
||||
localhost/hmac-file-server:latest -config /app/config.toml
|
||||
|
||||
# Stop and cleanup
|
||||
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
|
||||
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
|
||||
|
||||
# Reload configuration
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
# For system-wide installation, use: WantedBy=multi-user.target
|
Reference in New Issue
Block a user