Files
pic/QUICKSTART.md
T
roof 10ac15d9fe docs: Phase 7 — update docs to reflect optional services migration
Email, calendar, and files are now optional store services, not always-on
builtins. Updated README, QUICKSTART, Wiki, and service-developer-guide to
reflect: dynamic nav, optional service install flow, correct egress
identifiers (wireguard_ext/default vs wireguard/cell_internet), removed
builtin/store distinction from manifest reference, 7 core containers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 17:10:48 -04:00

6.1 KiB
Raw Blame History

Quick Start

This guide walks through a first-time PIC installation on a clean Linux host.


Prerequisites

  • Linux x86-64 host — Debian, Ubuntu, Fedora, RHEL, or Alpine
  • 2 GB+ RAM, 10 GB+ disk
  • Always-required ports: 53, 80, 443, 51820/udp
  • Email service only (when installed): 25, 587, 993

The installer handles all software dependencies (git, docker, make, etc.) automatically.


curl -fsSL https://install.pic.ngo | sudo bash

Always review the script before running it:

curl -fsSL https://install.pic.ngo | less

The installer:

  1. Detects your OS and installs Docker, git, make via the system package manager
  2. Creates a pic system user and adds it to the docker group
  3. Clones the repository to /opt/pic
  4. Runs make install (generates keys and config, writes a systemd unit)
  5. Runs make start-core to bring up the core containers
  6. Waits for the API to respond, then prints the wizard URL

When it finishes, open the URL it prints:

http://<host-ip>:8081/setup

Option B — Manual install

Use this if you want to control where PIC is installed, or if you are installing on a machine that already has Docker.

git clone https://git.pic.ngo/roof/pic.git pic
cd pic
sudo make install
make start-core

Then open http://<host-ip>:8081 in a browser.


Complete the setup wizard

The setup wizard appears automatically on first start. All API requests redirect to /setup until it is finished.

The wizard asks for:

  • Cell name — used for hostnames and DDNS subdomain. Lowercase letters, digits, hyphens, 231 characters. Example: myhome.
  • Domain mode — how HTTPS certificates are issued:
    • pic_ngo — automatic <cell-name>.pic.ngo subdomain with Let's Encrypt via DNS-01 (recommended for internet-facing cells)
    • cloudflare — Let's Encrypt via Cloudflare DNS-01 (bring your own domain)
    • duckdns — Let's Encrypt via DuckDNS DNS-01
    • http01 — Let's Encrypt via HTTP-01 (no wildcard; cell must be reachable on port 80)
    • lan — internal CA, no internet required (for LAN-only installs)
  • Timezone
  • Services to install — email, calendar, files (optional; installed in the background after setup completes; can be added later via the Services store page)
  • Admin password — minimum 12 characters, must contain uppercase, lowercase, and a digit

Click Complete Setup. The wizard creates the admin account, writes cell identity to config/api/cell_config.json, and redirects to the login page. Any services you selected begin installing in the background.


Log in

After the wizard you are redirected to /login.

  • Username: admin
  • Password: the password you set in the wizard

Add a WireGuard peer

Go to Peers in the sidebar.

  1. Click Add Peer.
  2. Enter a peer name (e.g. laptop).
  3. The API generates a key pair and assigns the next available VPN IP automatically.
  4. Click the QR code icon to display the peer configuration as a QR code.
  5. Scan the QR code with a WireGuard client (Android, iOS, or the WireGuard desktop app).

Once connected, *.cell names resolve through the cell's CoreDNS and traffic can be routed through the cell.


Installing and managing services

Email, calendar, and file storage are optional services installed from the built-in service store. They are not running by default.

To install a service:

  1. Go to Services in the sidebar.
  2. Find the service card (Email, Calendar, Files, or any other listed service).
  3. Click Install. PIC fetches the manifest, starts the container, and wires up DNS and Caddy routes automatically.
  4. The service appears in the sidebar navigation once installation completes.

To check service status:

The Services page shows each installed service as "running" or "stopped". You can also check via the API:

curl -s http://<host-ip>:3000/api/services/active

To uninstall a service:

Click Uninstall on the service card. The container is stopped and removed. Data in data/services/<id>/ is kept on disk unless you delete it manually.


Day-to-day operations

# Check container status and API health
make status

# Follow logs from all services
make logs

# Follow logs from a single service
make logs-api
make logs-wireguard
make logs-caddy

# Open a shell inside a container
make shell-api
make shell-dns

Backup and restore

make backup      # archives config/ and data/ into backups/cell-backup-<timestamp>.tar.gz
make restore     # list available backups

To restore manually:

tar -xzf backups/cell-backup-YYYYMMDD-HHMMSS.tar.gz
make start

Updating PIC

make update      # git pull + rebuild + restart

Uninstalling

make uninstall   # stops containers; prompts to also delete config/ and data/

Troubleshooting

Containers not starting

make logs
make logs-api

Look for errors about missing config files or port conflicts.

Port 53 already in use

On Ubuntu and Debian, systemd-resolved listens on port 53. Disable it:

sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf

Then run make start again.

WireGuard container fails to load the kernel module

sudo modprobe wireguard

On minimal installs you may need wireguard-tools and the kernel headers for the running kernel.

API returns 428 and redirects to /setup

The first-run wizard has not been completed. Open http://<host-ip>:8081 and finish the wizard.

API returns 401 / UI shows "Not authenticated"

Your session expired or you have not logged in. Go to http://<host-ip>:8081/login.

API returns 503 "Authentication not configured"

The auth file exists but contains no accounts. To recover:

make reset-admin-password

This generates a new admin password and prints it.

Forgot the admin password

make show-admin-password    # print current password
make reset-admin-password   # generate a new random password