Skip to content

tobias-kaerst-software/papercloud

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Papercloud

Infrastructure-as-code for a self-hosted Paperless-ngx setup on Hetzner Cloud, managed with OpenTofu (Terraform). The stack includes Traefik as a reverse proxy, Proton Bridge for email ingestion, Paperless AI for automatic document tagging, automated backups to Bunny CDN, and Tailscale for secure remote access.

Demo

Prerequisites

  • Mise installed locally (mise installs opentofu for you)
  • A Hetzner Cloud account
  • A Tailscale account
  • A Bunny CDN account
  • A domain with DNS pointing to the Hetzner VPS IP

Setup

1. Hetzner Cloud

  1. Create a new project in the Hetzner Cloud Console
  2. Navigate to Security → API Tokens and generate a token with Read & Write permissions
  3. Copy the token - this is your hcloud_token

2. Tailscale

  1. Create a Tailscale account
  2. Go to Settings → Keys and generate an Auth Key (reusable, ephemeral)
  3. Copy the key - this is your tailscale_key
  4. After the VPS is provisioned, find the machine in the Tailscale admin console and disable key expiry so the server stays connected permanently

3. Bunny CDN

  1. Create a Bunny CDN account
  2. Go to Storage and create a new storage zone
    • Tier: Standard
    • Replication: one replication region of your choice
  3. Copy the storage zone name - this is bunnycdn.storage_zone
  4. Open the storage zone and go to the FTP & API Access tab
  5. Copy the Password (not the main account API key) — this is bunnycdn.api_key

4. Proton Bridge (one-time initialization)

Before or after the first tofu apply, the Proton Bridge container data directory must be initialized on the server. SSH into the VPS after it is created and run:

docker run --rm -it \
  -v /home/deploy/docker/protonbridge/data:/root \
  shenxn/protonmail-bridge:3.19.0-1 init

Follow the interactive prompts to log in with your Proton account credentials. After a successful login, the bridge will output the SMTP credentials (host, port, username, password) when you prompt info needed to configure Paperless email consumption.

Reference: protonmail-bridge-docker

5. Configure terraform.tfvars

Copy the example below to infrastructure/terraform.tfvars and fill in your values:

# Passphrase used to encrypt the OpenTofu state file at rest
encryption_passphrase = "..."

# Hetzner Cloud API token
hcloud_token = "..."

# Tailscale auth key
tailscale_key = "tskey-auth-..."

# VPS and storage box configuration (defaults shown)
vps     = { type = "cx33", location = "fsn1" }
storage = { type = "bx11", location = "fsn1", mount_path = "/mnt/storage" }

# Public hostname — subdomains paperless.*, traefik.*, paperless-ai.* will be created
hostname = "papercloud.example.com"

# Admin credentials for Paperless and the Traefik dashboard
admin_email    = "you@example.com"
admin_username = "admin"
admin_password = "..."

# Basic auth hash for the Traefik dashboard (see below for generation)
admin_basic_auth = "admin:$$2a$$12$$..."

# Bunny CDN backup storage
bunnycdn = {
  storage_zone = "my-paperless-backup"   # storage zone name
  api_key      = "..."                   # storage zone password (not the account API key)
  path         = "backups"
}

# Number of backups to retain before purging older ones
backup_retention_count = 7

Generating the Traefik basic auth hash

echo $(htpasswd -nbB USER "PASSWORD") | sed -e s/\\$/\\$\\$/g

Replace USER and PASSWORD with your desired credentials. The output goes directly into admin_basic_auth.

Deploy

mise run deploy

Backups

Backups run nightly at 02:00 UTC via cron and are uploaded to Bunny CDN, retaining the last backup_retention_count archives. Make sure to check if the backups are working correctly instead of trusting this implementation blindly.

About

Hetzner Infrastructure & Provisioning to selfhost a paperless ngx instance with automatic backups and ai support.

Resources

Stars

Watchers

Forks

Contributors