Privacy Tools Guide

Self-hosting privacy tools eliminates reliance on third-party services. You control the hardware, the data, and the backups. Setting up a secure home server for privacy tools (password managers, VPN, note storage) requires understanding networks, containers, and Linux hardening—but the result is complete digital autonomy.

Why Self-Host Privacy Tools?

Third-party password managers, file storage, and VPN services trust companies not to breach, not to change terms, not to sell access. Self-hosting removes that dependency:

The tradeoff: You’re responsible for updates, backups, and security.

Hardware Selection

Minimum Specs for Home Privacy Server

CPU: 2-4 cores (Intel N100, AMD Ryzen 5 PRO, or ARM-based)
RAM: 8-16 GB (allows multiple containerized services)
Storage: 500GB-2TB SSD (for system + encrypted backups)
Power: Low-wattage (30-65W) to run 24/7
Networking: 1Gbps Ethernet (Wi-Fi unreliable for server)
Form factor: Small enough to hide, not a full desktop tower

Option 1: Raspberry Pi 4 or 5 ($75-150)

Specs:
- ARM-based (bcm2711 or bcm2712)
- 4-8GB RAM
- 500GB-1TB USB SSD (external, not SD card)
- 24/7 safe to run (low power draw)
- Ubuntu/Debian support excellent

Limitations:
- Slower than x86 (fine for password manager, VPN, file sync)
- Some services lack ARM binaries (research before buying)
- USB latency (use high-quality SSD enclosure)

Best for: Minimal setup, password manager + VPN

Option 2: Intel NUC ($200-400)

Specs:
- Intel N100 or equivalent (quad-core)
- 8-16GB RAM (upgradeable)
- 512GB-1TB M.2 SSD (fast, reliable)
- 24/7 safe (fanless models available)
- Full x86 compatibility (all software works)

Best for: Running 3+ services simultaneously, guaranteed compatibility

Option 3: Used Mini PC ($150-300)

Examples: Lenovo ThinkCentre M90, Dell OptiPlex 3050
Specs:
- i5-7th gen equivalent
- 8-16GB RAM (often upgradeable)
- 512GB SSD
- 24/7 capable
- x86 full compatibility

Best for: Budget-conscious, maximum power per dollar

Network Setup: Safe Remote Access

Never expose your home IP directly. Use a VPN for remote access:

Device (outside home)
  → VPN server (your home)
    → Internal privacy apps (password manager, etc.)
Setup:
1. Install WireGuard on home server
2. Generate client config (private key + server public key)
3. Install client on phone/laptop
4. Connect to home server via encrypted tunnel
5. Access internal apps through tunnel

Benefits:
- 10-50x faster than OpenVPN (lightweight protocol)
- Smaller attack surface (500 lines of code vs. 400,000 for OpenVPN)
- Modern cryptography (Curve25519)
- Supports roaming (seamless handoff between networks)

WireGuard installation (Ubuntu):

# Install WireGuard
sudo apt install wireguard wireguard-tools

# Generate server keys
wg genkey | tee server_private.key | wg pubkey > server_public.key

# Generate client keys
wg genkey | tee client_private.key | wg pubkey > client_public.key

# Create WireGuard config
sudo nano /etc/wireguard/wg0.conf

Content of /etc/wireguard/wg0.conf:

[Interface]
PrivateKey = [contents of server_private.key]
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = [contents of client_public.key]
AllowedIPs = 10.0.0.2/32

Option 2: Reverse SSH Tunnel (Lightweight)

For minimal setup, SSH tunnel provides encrypted access without dedicated VPN software:

# On home server, create persistent tunnel
ssh -R 5000:localhost:3000 \
  -i ~/.ssh/id_ed25519 \
  remote_server_user@remote_server_ip \
  -N -T

# Port 5000 on remote server tunnels to port 3000 on home server
# Access home app from anywhere: ssh://remote_server:5000

Limitation: Requires remote VPS (adds cost and third-party dependency)

OS Hardening

Your home server should be as locked-down as a production server.

Ubuntu 24.04 LTS Hardening Checklist

# 1. Update system
sudo apt update && sudo apt upgrade -y
sudo apt install -y unattended-upgrades
sudo systemctl enable unattended-upgrades

# 2. Disable unnecessary services
sudo systemctl disable bluetooth.service
sudo systemctl disable cups.service  # Printer daemon

# 3. Configure firewall
sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 51820/udp  # WireGuard
sudo ufw allow 443/tcp   # HTTPS for web apps

# 4. SSH hardening
sudo nano /etc/ssh/sshd_config
# Set: PermitRootLogin no
# Set: PasswordAuthentication no
# Set: PubkeyAuthentication yes
# Set: Port 2222 (non-standard)

sudo systemctl restart ssh

# 5. Fail2ban (prevent brute force)
sudo apt install -y fail2ban
sudo systemctl enable fail2ban

# 6. SELinux or AppArmor
sudo aa-enabled  # Check AppArmor status

# 7. Disable IPv6 if not using
sudo nano /etc/sysctl.conf
# Add: net.ipv6.conf.all.disable_ipv6 = 1

Containerized Privacy Tools

Use Docker for isolated, easy-to-update services.

Install Docker and Docker Compose

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

Docker Compose Stack: Privacy Tools

Create /home/user/privacy-stack/docker-compose.yml:

version: '3.8'

services:
  # Password Manager
  bitwarden:
    image: vaultwarden/server:latest
    container_name: bitwarden
    restart: always
    environment:
      DOMAIN: https://passwords.local
      SHOW_PASSWORD_HINT: "false"
      _IP_HEADER: "CF-Connecting-IP"
      _DOMAIN_ORIGIN: https://passwords.local
    volumes:
      - ./data/bitwarden:/data
    networks:
      - privacy
    ports:
      - "80:80"
    labels:
      - "com.example.description=Bitwarden password manager"

  # Note Storage (Markdown-based)
  joplin:
    image: joplin/server:latest
    container_name: joplin-server
    restart: always
    environment:
      APP_BASE_URL: https://notes.local
      DB_CLIENT: pg
      POSTGRES_PASSWORD: changeme
      POSTGRES_DATABASE: joplin
      POSTGRES_HOST: postgres
    depends_on:
      - postgres
    volumes:
      - ./data/joplin:/home/joplin
    networks:
      - privacy
    ports:
      - "22300:22300"

  # File Sync (Nextcloud)
  nextcloud:
    image: nextcloud:latest
    container_name: nextcloud
    restart: always
    environment:
      NEXTCLOUD_ADMIN_USER: admin
      NEXTCLOUD_ADMIN_PASSWORD: changeme
      NEXTCLOUD_TRUSTED_DOMAINS: files.local
    volumes:
      - ./data/nextcloud:/var/www/html
      - ./storage/nextcloud:/var/www/html/data
    depends_on:
      - postgres
    networks:
      - privacy
    ports:
      - "8080:80"

  # Database (PostgreSQL)
  postgres:
    image: postgres:16-alpine
    container_name: privacy-db
    restart: always
    environment:
      POSTGRES_PASSWORD: changeme
      POSTGRES_INITDB_ARGS: "-c ssl=on"
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    networks:
      - privacy
    # No external ports - only internal access

  # Reverse Proxy (Nginx)
  nginx:
    image: nginx:alpine
    container_name: privacy-reverse-proxy
    restart: always
    volumes:
      - ./config/nginx.conf:/etc/nginx/nginx.conf
      - ./certs:/etc/nginx/certs:ro
    networks:
      - privacy
    ports:
      - "443:443"
      - "80:80"
    depends_on:
      - bitwarden
      - joplin-server
      - nextcloud

networks:
  privacy:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

TLS Certificates (HTTPS)

Self-signed certificates for internal access:

# Generate self-signed cert (valid 10 years)
openssl req -x509 -nodes -days 3650 \
  -newkey rsa:2048 \
  -keyout privacy-tools.key \
  -out privacy-tools.crt \
  -subj "/CN=*.local/O=Private/C=US"

# Store in /home/user/privacy-stack/certs/
mv privacy-tools.* ./certs/

Backup Strategy

Self-hosted servers are useless without backups.

# Daily encrypted backup to external drive
#!/bin/bash

BACKUP_DIR="/mnt/backup"
BACKUP_DATE=$(date +%Y-%m-%d)

# Backup database
docker exec privacy-db pg_dump -U postgres joplin | \
  gzip | \
  gpg --symmetric --cipher-algo AES256 \
  > $BACKUP_DIR/joplin-$BACKUP_DATE.sql.gz.gpg

# Backup encrypted data volumes
tar czf - ./data | \
  gpg --symmetric --cipher-algo AES256 \
  > $BACKUP_DIR/privacy-data-$BACKUP_DATE.tar.gz.gpg

# Verify backup integrity
gpg --decrypt $BACKUP_DIR/privacy-data-$BACKUP_DATE.tar.gz.gpg | \
  tar tzf - > /dev/null && \
  echo "Backup verified: $BACKUP_DATE"

# Keep only last 30 days
find $BACKUP_DIR -mtime +30 -delete

Run daily via cron:

crontab -e
# Add: 2 3 * * * /home/user/privacy-stack/backup.sh

Monitoring and Maintenance

# Check container health
docker ps

# View logs
docker logs bitwarden

# Update containers
docker-compose pull
docker-compose up -d

# Disk usage
du -sh ./data/*

# Monitor from outside
# Set up Prometheus + Grafana in same stack

Security Checklist

Troubleshooting Common Issues

WireGuard slow/disconnecting: → Check MTU (default 1420, try 1380) → Enable keep-alive in client config

Nextcloud container crashing: → Database password mismatch, check env vars → Storage permission denied, run: sudo chown -R www-data:www-data ./storage

HTTPS certificate errors: → Self-signed cert—add exception in browser (expected, safe for local) → Regenerate cert if CN name wrong

Out of disk space: → Trim old backups: find ./data -type f -mtime +30 -delete → Check logs: docker logs <container> | tail -100

Built by theluckystrike — More at zovo.one