diff --git a/Admin-Backup.md b/Admin – Back Up and Restore.md similarity index 83% rename from Admin-Backup.md rename to Admin – Back Up and Restore.md index d9b13c2..45e0bd4 100644 --- a/Admin-Backup.md +++ b/Admin – Back Up and Restore.md @@ -1,4 +1,6 @@ -# Backup and Restore +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Admin – Back Up and Restore --- @@ -29,6 +31,7 @@ The API-driven backup captures everything above, and additionally: ### Via make (quick archive) ```bash +# Run on: the cell server host, from /opt/pic make backup ``` @@ -46,10 +49,10 @@ To encrypt the archive with a passphrase: POST /api/config/backup Content-Type: application/json -{"passphrase": "your-passphrase-here"} +{"passphrase": ""} ``` -The encrypted file is named `.tar.gz.age`. The plaintext staging directory is removed immediately after encryption. Fernet encryption with an scrypt-derived key is used. +The encrypted file is named `.tar.gz.age`. The plaintext staging directory is removed immediately after encryption. The archive uses Fernet encryption with an scrypt-derived key. Both the unencrypted and encrypted archive files are written with permissions `0600`. @@ -60,6 +63,7 @@ Both the unencrypted and encrypted archive files are written with permissions `0 ### From a `make backup` archive ```bash +# Run on: the cell server host, from /opt/pic tar -xzf backups/cell-backup-YYYYMMDD-HHMMSS.tar.gz make restart ``` @@ -78,7 +82,7 @@ For an encrypted archive: POST /api/config/restore/ Content-Type: application/json -{"passphrase": "your-passphrase-here"} +{"passphrase": ""} ``` The restore process: @@ -96,7 +100,7 @@ After an API restore, run `make restart` to ensure all containers pick up the re --- -## Backup schedule recommendation +## Backup schedule PIC does not run automated backups on a schedule. Set up a cron job or systemd timer to call `make backup` (or the API endpoint) regularly. @@ -108,8 +112,10 @@ Example cron (runs nightly at 2 AM from the PIC directory): --- -## Important +## Security reminder -A backup contains everything needed to fully reconstruct your cell — including your WireGuard private key, internal CA, and admin credentials. Treat backup files with the same security as you would a password manager export. +A backup contains everything needed to fully reconstruct your cell — including your WireGuard private key, internal CA, and admin credentials. Treat backup files with the same care as a password manager export. If you use passphrase encryption, store the passphrase separately from the backup file. If you lose the passphrase, the backup is unrecoverable. + +Internals: see [[Dev – Architecture]] diff --git a/Admin-Connectivity.md b/Admin – Configure Connectivity.md similarity index 72% rename from Admin-Connectivity.md rename to Admin – Configure Connectivity.md index 70ddb49..59555ab 100644 --- a/Admin-Connectivity.md +++ b/Admin – Configure Connectivity.md @@ -1,4 +1,6 @@ -# Connectivity +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Admin – Configure Connectivity The Connectivity feature lets you route individual peers (or services) through an alternate exit instead of the cell's default internet gateway. This is useful for privacy, geographic routing, or compliance requirements. @@ -8,7 +10,7 @@ The Connectivity feature lets you route individual peers (or services) through a ### Connection instances -A **connection** is a named, configured instance of an exit type. You create as many as you need and give each a name (e.g. "Home VPN", "US Exit", "Tor"). +A **connection** is a named, configured instance of an exit type. You create as many as you need and give each a name (for example, "Home VPN", "US Exit", "Tor"). Once a connection is created, you assign peers to it. Each peer uses exactly one connection (or the default gateway if none is assigned). @@ -22,7 +24,7 @@ Connection types: | `sshuttle` | SSH tunnel via sshuttle | `sshuttle` | | `proxy` | HTTP/SOCKS5 upstream proxy via redsocks | `proxy` | -**Tor is limited to one instance per cell.** All other types support multiple named instances. +> ℹ️ **Note:** Tor is limited to one instance per cell. All other types support multiple named instances. ### Fail-open vs fail-closed @@ -31,7 +33,11 @@ When the exit a peer is assigned to goes down, PIC decides whether to block the - **Fail-closed** (default for all types except Tor): if the exit is down, traffic from that peer is blocked by a kill-switch FORWARD rule in `cell-wireguard`. The peer loses internet access until the exit recovers. - **Fail-open** (default for Tor only): if the exit is down, traffic falls back to the default gateway. -You can override the fail-open behaviour per peer with `PUT /api/connectivity/peers//failopen`. +You can override the fail-open behaviour per peer from the peer's detail page or via: + +``` +PUT /api/connectivity/peers//failopen +``` ### Cell-relay connections @@ -41,14 +47,31 @@ A **cell-relay** connection is auto-derived from a cell-to-cell link where the r ## Setting up a connection -1. Install the corresponding exit service from the Services catalog first (e.g. install `wireguard-ext` before creating a `wireguard_ext` connection). -2. Go to **Connectivity** in the sidebar. -3. Click **Add Connection**. -4. Choose the type, give it a name, and fill in the required config (e.g. upload the WireGuard config file for `wireguard_ext`, or supply the host/user/port for `sshuttle`). -5. Click **Save**. +### Purpose + +Route one or more peers through an alternate internet exit. + +### Prerequisites + +Install the corresponding exit service from the Services catalog first (for example, install `wireguard-ext` before creating a `wireguard_ext` connection). See [[Admin – Manage Services]]. + +### Steps + +1. Go to **Connectivity** in the sidebar. +2. Click **Add Connection**. +3. Choose the type, give it a name, and fill in the required config (for example, upload the WireGuard config file for `wireguard_ext`, or supply the host/user/port for `sshuttle`). +4. Click **Save**. The connection now appears in the list with a health status indicator. +### Verification + +The connection should appear with a `working` status. If it shows `down` or `unknown`, check the exit service logs from the Logs page. + +### Rollback + +Delete the connection from the Connectivity page (after unassigning any peers). The exit service remains installed; only the connection instance is removed. + --- ## Assigning a peer to a connection @@ -89,19 +112,6 @@ Health check mechanism by type: --- -## Connectivity and routing internals - -PIC implements exit routing using `fwmark` and `ip rule` / `ip route` inside the `cell-wireguard` container. Each connection instance is allocated: - -- A unique fwmark (starting from `0x1000`, stride `0x10`) -- A dedicated routing table (starting from table `1000`) -- For `wireguard_ext` and `openvpn`: a named interface (e.g. `wgext_`, `ovpn_`) -- For `tor`, `sshuttle`, `proxy`: a redirect port (starting from `9100`) - -This is the v2 connectivity model. If you have a cell upgraded from an older version, PIC automatically migrates the single legacy exit configuration to a named connection instance on first access. - ---- - ## Removing a connection A connection cannot be removed while peers are assigned to it. First unassign all peers (set their exit to `default`), then delete the connection from the Connectivity page. Deleting a connection that is still in use returns HTTP 409. @@ -112,4 +122,4 @@ A connection cannot be removed while peers are assigned to it. First unassign al Cell-to-cell links (site-to-site WireGuard tunnels between two PIC cells) are managed from the **Cell Network** page, not the Connectivity page. When a remote cell offers its internet exit, the resulting `cell_relay` connection appears automatically in the Connectivity page's connection list and can be assigned to peers like any other connection. -See the [Cell Network section in Dev Architecture](Dev-Architecture) for the technical details. +Internals: see [[Dev – Architecture]] diff --git a/Admin-Domains-TLS.md b/Admin – Configure Domains and TLS.md similarity index 83% rename from Admin-Domains-TLS.md rename to Admin – Configure Domains and TLS.md index 6ae91d7..84caac3 100644 --- a/Admin-Domains-TLS.md +++ b/Admin – Configure Domains and TLS.md @@ -1,4 +1,6 @@ -# Domains and TLS +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Admin – Configure Domains and TLS PIC supports five domain modes. The mode determines how your cell gets an HTTPS certificate and whether it registers a public DNS name. @@ -16,11 +18,14 @@ PIC supports five domain modes. The mode determines how your cell gets an HTTPS ### `pic_ngo` -PIC registers `.pic.ngo` with the `ddns.pic.ngo` service during setup. A background thread re-checks and re-publishes your public IP every 5 minutes. The DDNS service issues a wildcard Let's Encrypt certificate via DNS-01 challenge, so all subdomains (`mail.*`, `calendar.*`, `files.*`, etc.) are covered by one cert. +PIC registers `.pic.ngo` with the `ddns.pic.ngo` service during setup. A background thread re-checks and re-publishes your public IP every 5 minutes. The DDNS service issues a wildcard Let's Encrypt certificate via DNS-01 challenge, so all subdomains (`mail.*`, `calendar.*`, `files.*`, and others) are covered by one cert. **Requirements:** + - Accurate host clock — see [Host NTP](#host-ntp) below -- Port 80 and 443 reachable from the internet (for the ACME challenge and for clients) +- Ports 80 and 443 reachable from the internet (for the ACME challenge and for clients) + +Registration uses a time-based one-time password (TOTP) to prevent unauthorised subdomain registration on `pic.ngo`. This is why accurate host time is required. ### `cloudflare` @@ -36,7 +41,7 @@ Let's Encrypt issues individual certificates for each subdomain by making an HTT ### `lan` -PIC's internal certificate authority (managed by `VaultManager`) issues TLS certificates. No internet access is required. Clients that need to trust your cell's HTTPS need to import the internal CA certificate, available from the Vault page in the admin dashboard. +PIC's internal certificate authority (managed by `VaultManager`) issues TLS certificates. No internet access is required. Clients that need to trust your cell's HTTPS need to import the internal CA certificate, which is available from the Vault page in the admin dashboard. --- @@ -77,8 +82,6 @@ For `pic_ngo`, `cloudflare`, and `duckdns` modes, a background thread in the API DDNS configuration lives in `config/api/cell_config.json` under the `ddns` key. The bearer token (for `pic_ngo`) is stored in `data/api/.ddns_token`. -Registration uses a time-based OTP (TOTP) to prevent unauthorised subdomain registration on `pic.ngo`. This is why accurate host time is required. - --- ## Host NTP @@ -101,7 +104,7 @@ sudo dnf install -y chrony && sudo systemctl enable --now chronyd sudo apk add chrony && sudo rc-update add chronyd default && sudo service chronyd start ``` -The `cell-ntp` container (chrony) serves NTP to VPN-connected peers separately from the host chrony. +The `cell-ntp` container (chrony) serves NTP to VPN-connected peers separately from the host chrony. These are two different chrony processes serving different purposes. --- @@ -114,4 +117,6 @@ You can change domain modes from the Settings page in the admin dashboard. Chang 3. Re-registers or deregisters the DDNS subdomain as appropriate 4. Rebuilds CoreDNS split-horizon zones -If you change from `pic_ngo` to `lan`, the DDNS registration is not automatically removed. You will need to do that manually if needed. +> ℹ️ **Note:** If you change from `pic_ngo` to `lan`, the DDNS registration is not automatically removed. You will need to do that manually if needed. + +Internals: see [[Dev – Architecture]] diff --git a/Admin-Setup.md b/Admin – Install and First Run.md similarity index 72% rename from Admin-Setup.md rename to Admin – Install and First Run.md index 1fd464d..d7d3bfb 100644 --- a/Admin-Setup.md +++ b/Admin – Install and First Run.md @@ -1,16 +1,20 @@ -# Setup and First Run +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Admin – Install and First Run ## Installation ### Option A — one-line installer (recommended) ```bash +# Run on: your Linux server, as a user with sudo access curl -fsSL https://install.pic.ngo | sudo bash ``` -Before running any script as root, review it: +Before running any script as root, review it first: ```bash +# Run on: your Linux server curl -fsSL https://install.pic.ngo | less ``` @@ -23,7 +27,7 @@ The install log is always written to `/var/log/pic-install.log`. If anything fai The installer runs 7 steps: -1. Detects your OS and package manager (apt / dnf / apk) +1. Detects your OS and package manager (`apt` / `dnf` / `apk`) 2. Installs Docker, git, make, and host chrony (NTP) 3. Creates a `pic` system user and adds it to the `docker` group 4. Clones the repository to `/opt/pic` @@ -42,6 +46,7 @@ Open your browser: http://:8081/setup Use this if you want to control the install path or if Docker is already installed: ```bash +# Run on: your Linux server, as root or with sudo git clone https://git.pic.ngo/roof/pic.git pic cd pic sudo make install @@ -51,7 +56,14 @@ make start-core Install host chrony before running `make install` if you plan to use `pic.ngo` domain mode: ```bash +# Debian / Ubuntu sudo apt-get install -y chrony && sudo systemctl enable --now chrony + +# Fedora / RHEL +sudo dnf install -y chrony && sudo systemctl enable --now chronyd + +# Alpine +sudo apk add chrony && sudo rc-update add chronyd default && sudo service chronyd start ``` Then open `http://:8081/setup`. @@ -65,7 +77,7 @@ The wizard appears automatically on first start. All API requests redirect to `/ The wizard collects: - **Cell name** — used for hostnames and the DDNS subdomain. Must start with a lowercase letter, be 2–31 characters, and contain only lowercase letters, digits, and hyphens. Example: `myhome`. -- **Domain mode** — see [Domains and TLS](Admin-Domains-TLS) for details. +- **Domain mode** — see [[Admin – Configure Domains and TLS]] for details. - **Timezone** — your local timezone, used for log timestamps. - **Services to install** — optional services (email, calendar, files) to start installing in the background after setup completes. You can install them later from the Services page instead. - **Admin password** — minimum 12 characters; must contain at least one uppercase letter, one lowercase letter, and one digit. @@ -94,14 +106,14 @@ The three core identity values are: These are stored in `config/api/cell_config.json` under the `_identity` key. Do not edit this file directly — use the Settings page in the UI or the API. -The cell's WireGuard VPN uses the subnet `10.0.0.0/24` by default (the server address is `10.0.0.1/24`). This is configured in `api/wireguard_manager.py` and is not currently exposed in the wizard UI. +The cell's WireGuard VPN uses the subnet `10.0.0.0/24` (the server address is `10.0.0.1/24`). This is configured in `api/wireguard_manager.py` and is not currently exposed in the wizard UI. --- ## After the wizard -- Go to **Peers** to add devices to the VPN — see [Peers](Admin-Peers). -- Go to **Services** to install or manage optional services — see [Services Catalog](Admin-Services). +- Go to **Peers** to add devices to the VPN — see [[Admin – Manage Peers]]. +- Go to **Services** to install or manage optional services — see [[Admin – Manage Services]]. - Go to **Settings** to change domain mode, DDNS config, or admin password. --- @@ -111,6 +123,7 @@ The cell's WireGuard VPN uses the subnet `10.0.0.0/24` by default (the server ad If you forget the admin password: ```bash +# Run on: the cell server host, from /opt/pic make show-admin-password # print the current password make reset-admin-password # generate and set a new random password ``` @@ -120,6 +133,7 @@ make reset-admin-password # generate and set a new random password ## Updating PIC ```bash +# Run on: the cell server host, from /opt/pic make update # git pull + rebuild all images + restart ``` @@ -128,7 +142,12 @@ make update # git pull + rebuild all images + restart ## Uninstalling ```bash +# Run on: the cell server host, from /opt/pic make uninstall ``` -This stops all containers and removes the systemd unit. It then asks whether to also delete `config/` and `data/`. Answering yes performs a full wipe — all configuration, keys, peer data, and service data are deleted and cannot be recovered without a backup. +This stops all containers and removes the systemd unit. It then asks whether to also delete `config/` and `data/`. + +> ⚠️ **Warning:** Answering yes to the data deletion prompt performs a full wipe — all configuration, keys, peer data, and service data are deleted and cannot be recovered without a backup. + +Internals: see [[Dev – Install Internals]] diff --git a/Admin-Logging-Audit.md b/Admin – Logging and Audit.md similarity index 80% rename from Admin-Logging-Audit.md rename to Admin – Logging and Audit.md index 4a0e19e..07c3457 100644 --- a/Admin-Logging-Audit.md +++ b/Admin – Logging and Audit.md @@ -1,4 +1,6 @@ -# Logging and Audit +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Admin – Logging and Audit --- @@ -6,7 +8,7 @@ PIC has two separate log-level axes: -1. **Python service log levels** — control verbosity for the Flask API's manager modules (e.g. `network`, `wireguard`, `email`). Changes apply hot to the running process. +1. **Python service log levels** — control verbosity for the Flask API's manager modules (for example, `network`, `wireguard`, `email`). Changes apply hot to the running process. 2. **Container log levels** — control verbosity inside specific containers (Caddy, CoreDNS, WireGuard, mailserver). Some changes apply hot; others require a container restart. ### Python log levels @@ -80,6 +82,7 @@ GET /api/logs/search?q=&service= From the command line: ```bash +# Run on: the cell server host, from /opt/pic make logs # follow all container logs via docker compose make logs-api # follow the api container log make logs-wireguard # follow the wireguard container log @@ -92,11 +95,11 @@ make logs-caddy # follow the caddy container log PIC maintains an append-only, hash-chained audit trail of administrative actions. Every mutating API request (`POST`, `PUT`, `DELETE`, `PATCH`) is recorded with: -- Who — username, role, and source IP -- What — action type and target (e.g. `peer_add`, `peer:laptop`) -- When — UTC timestamp -- Result — `success` or `failure` -- Summary — a human-readable description; key **names** only, never values (secrets are never written) +- **Who** — username, role, and source IP +- **What** — action type and target (for example, `peer_add`, `peer:laptop`) +- **When** — UTC timestamp +- **Result** — `success` or `failure` +- **Summary** — a human-readable description; key **names** only, never values (secrets are never written) The chain uses a per-entry SHA-256 hash linking each entry to the previous one. Tampering with the log file is detectable by verifying the chain. @@ -134,4 +137,6 @@ The audit log lives at `data/api/audit/audit.log` (a JSONL file). It rotates at ### What is not audited -Read-only requests (`GET`) and diagnostic POST endpoints (e.g. connectivity test) are not recorded. The audit log tracks state changes only. +Read-only requests (`GET`) and diagnostic POST endpoints (for example, connectivity test) are not recorded. The audit log tracks state changes only. + +Internals: see [[Dev – API Reference]] diff --git a/Admin-Peers.md b/Admin – Manage Peers.md similarity index 65% rename from Admin-Peers.md rename to Admin – Manage Peers.md index ce63d43..b8c8391 100644 --- a/Admin-Peers.md +++ b/Admin – Manage Peers.md @@ -1,4 +1,6 @@ -# Peers +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Admin – Manage Peers A **peer** is a device or person that connects to your cell over WireGuard. Each peer gets a private key pair, a VPN IP address, and optionally an account on installed services. @@ -11,14 +13,16 @@ A **peer** is a device or person that connects to your cell over WireGuard. Each 3. Enter a peer name (letters, digits, underscores, hyphens, dots — max 64 characters). 4. Click **Save**. PIC generates a key pair and assigns the next available VPN IP automatically. +You should now see the new peer in the list with a VPN IP assigned. + --- ## Exporting a peer configuration After adding a peer: -- Click the **QR code** icon to show the configuration as a QR code. Scan it with the WireGuard mobile app. -- Click the **Download** icon to download the `.conf` file. Import it into the WireGuard desktop app. +- Click the **QR code** icon to show the configuration as a QR code. The peer can scan it with the WireGuard mobile app. +- Click the **Download** icon to download the `.conf` file. The peer imports it into the WireGuard desktop app. The configuration file contains the peer's private key. Treat it like a password. If a peer loses their configuration, you cannot retrieve the private key — delete the peer and create a new one. @@ -26,7 +30,7 @@ The configuration file contains the peer's private key. Treat it like a password ## Peer VPN IPs -VPN IPs are assigned sequentially from the WireGuard subnet (`10.0.0.0/24` by default). The cell's VPN address is `10.0.0.1`. Peers start from `10.0.0.2`. +VPN IPs are assigned sequentially from the WireGuard subnet (`10.0.0.0/24`). The cell's VPN address is `10.0.0.1`. Peers start from `10.0.0.2`. The IP is automatically included in the exported config's `AllowedIPs` field. @@ -34,7 +38,7 @@ The IP is automatically included in the exported config's `AllowedIPs` field. ## Per-peer routing -From the peer's detail page, you can set the peer's **exit connection** (default, or a named connection from the Connectivity page). See [Connectivity](Admin-Connectivity) for details. +From the peer's detail page, you can set the peer's **exit connection** (default, or a named connection from the Connectivity page). See [[Admin – Configure Connectivity]] for details. You can also set the peer's **fail-open** override: @@ -46,22 +50,23 @@ You can also set the peer's **fail-open** override: ## Per-peer service access -From the service pages (e.g. `/services/email`, `/services/calendar`), you can provision or revoke a peer's account on that service. When a peer is deleted, all their service accounts are removed automatically. +From the service pages (for example `/services/email`, `/services/calendar`), you can provision or revoke a peer's account on that service. When a peer is deleted, all their service accounts are removed automatically. --- ## Deleting a peer 1. Go to **Peers**, find the peer, and click **Delete**. -2. Confirm. PIC removes the peer from `wg0.conf`, removes their accounts on all installed services, and revokes any cell-to-cell routing entries for that peer. +2. Confirm. -The peer's WireGuard config (which they have on their device) stops working immediately after deletion — the server-side peer entry is gone. +> ⚠️ **Warning:** Deleting a peer is immediate and irreversible. PIC removes the peer from `wg0.conf`, removes their accounts on all installed services, and revokes any cell-to-cell routing entries for that peer. The peer's WireGuard config (which they have on their device) stops working immediately. --- ## Listing peers from the command line ```bash +# Run on: the cell server host, from /opt/pic make list-peers # calls the API and prints peer names and VPN IPs make show-routes # runs wg show inside the cell-wireguard container ``` diff --git a/Admin-Services.md b/Admin – Manage Services.md similarity index 83% rename from Admin-Services.md rename to Admin – Manage Services.md index cda18ec..c156112 100644 --- a/Admin-Services.md +++ b/Admin – Manage Services.md @@ -1,4 +1,6 @@ -# Services Catalog +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Admin – Manage Services Optional services are installed from the built-in service store. None of them run by default — only the six core containers start automatically. @@ -11,11 +13,11 @@ Optional services are installed from the built-in service store. None of them ru | `cell-caddy` | Caddy reverse proxy, TLS termination | | `cell-dns` | CoreDNS — `.cell` TLD and split-horizon DNS | | `cell-ntp` | chrony NTP server for VPN peers | -| `cell-wireguard` | WireGuard VPN (NET_ADMIN only, not privileged) | +| `cell-wireguard` | WireGuard VPN (`NET_ADMIN` capability only, not privileged) | | `cell-api` | Flask REST API | | `cell-webui` | React web UI (Nginx) | -DHCP was removed from PIC. The `cell-dns` container runs CoreDNS only. +> ℹ️ **Note:** PIC does not include a DHCP server. The `cell-dns` container runs CoreDNS only. --- @@ -53,7 +55,7 @@ Every store image is digest-pinned and signed by the PIC build pipeline. Before | `warn` | Verification failures are logged but installation proceeds. | | `off` | No verification. | -Leave it on `enforce` unless you are developing your own service images — see [Building Services](Dev-Building-Services). +Leave it on `enforce` unless you are developing your own service images — see [[Dev – Build a Store Service]]. --- @@ -80,13 +82,13 @@ These ports are only opened on the host when the email service is installed. ## Managing peer accounts on services -Each installed service can provision per-peer accounts. From the service's admin page (e.g. `/services/email`): +Each installed service can provision per-peer accounts. From the service's admin page (for example `/services/email`): 1. Go to the **Accounts** tab. 2. Click **Add Account** and enter the peer's username. PIC generates a password automatically, or you can supply one. 3. The peer can see their connection credentials from the peer dashboard. -To remove a peer's account, click **Remove** next to the account entry. When a peer is deleted from the Peers page, their accounts on all services are also removed. +To remove a peer's account, click **Remove** next to the account entry. When a peer is deleted from the Peers page, their accounts on all services are also removed automatically. --- @@ -95,7 +97,7 @@ To remove a peer's account, click **Remove** next to the account entry. When a p 1. Go to **Services** in the sidebar. 2. Click **Uninstall** on the service card. -The container is stopped and removed. Service data in `data/services//` is kept on disk. You must delete it manually if you want to free the space. Use the API-driven backup before uninstalling if you want to preserve user data — see [Backup and Restore](Admin-Backup). +The container is stopped and removed. Service data in `data/services//` is kept on disk. You must delete it manually if you want to free the space. Use the API-driven backup before uninstalling if you want to preserve user data — see [[Admin – Back Up and Restore]]. --- @@ -104,19 +106,23 @@ The container is stopped and removed. Service data in `data/services//` is k The Services page shows each installed service with a running/stopped indicator. You can also query the API: ```bash +# Run on: the cell server host (or via the VPN) curl -s http://127.0.0.1:3000/api/services/active ``` -To restart a service from the command line, use the container manager or: +To restart a service from the command line: ```bash +# Run on: the cell server host, from /opt/pic make shell-api -# then inside the container: -# the service manager's restart endpoint is POST /api/services/catalog//restart +# then inside the container, call: +# POST /api/services/catalog//restart ``` --- ## Connectivity exit services -The five connectivity exit services (`wireguard-ext`, `openvpn-client`, `tor`, `sshuttle`, `proxy`) integrate with the Connectivity feature. After installing one, you create a named connection instance from the **Connectivity** page and then assign peers to it. See [Connectivity](Admin-Connectivity) for details. +The five connectivity exit services (`wireguard-ext`, `openvpn-client`, `tor`, `sshuttle`, `proxy`) integrate with the Connectivity feature. After installing one, you create a named connection instance from the **Connectivity** page and then assign peers to it. See [[Admin – Configure Connectivity]] for details. + +Internals: see [[Dev – Architecture]] diff --git a/Admin-Monitoring-Troubleshooting.md b/Admin – Monitor and Troubleshoot.md similarity index 78% rename from Admin-Monitoring-Troubleshooting.md rename to Admin – Monitor and Troubleshoot.md index 0cf4366..e5b822d 100644 --- a/Admin-Monitoring-Troubleshooting.md +++ b/Admin – Monitor and Troubleshoot.md @@ -1,10 +1,13 @@ -# Monitoring and Troubleshooting +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Admin – Monitor and Troubleshoot --- ## Checking overall health ```bash +# Run on: the cell server host, from /opt/pic make status # container status + API health check at /health ``` @@ -33,6 +36,7 @@ Your session expired. Open `http://:8081/login`. The auth file exists but is empty. This should not happen in normal operation, but if it does: ```bash +# Run on: the cell server host, from /opt/pic make reset-admin-password ``` @@ -41,6 +45,7 @@ This prints a new random admin password. ### Forgot the admin password ```bash +# Run on: the cell server host, from /opt/pic make show-admin-password # print the current password make reset-admin-password # generate and set a new random password ``` @@ -48,6 +53,7 @@ make reset-admin-password # generate and set a new random password ### Containers not starting ```bash +# Run on: the cell server host, from /opt/pic make logs make logs-api ``` @@ -59,6 +65,7 @@ Look for error messages about missing config files, port conflicts, or Docker so On Ubuntu and Debian, `systemd-resolved` listens on port 53. Disable it: ```bash +# Run on: the cell server host, as root sudo systemctl disable --now systemd-resolved sudo rm /etc/resolv.conf echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf @@ -71,6 +78,7 @@ Then run `make start`. The WireGuard container runs unprivileged (`NET_ADMIN` capability only — not full `privileged` mode). It requires the WireGuard kernel module on the host. Load it manually: ```bash +# Run on: the cell server host, as root sudo modprobe wireguard ``` @@ -90,9 +98,9 @@ Split-horizon DNS is not working. Check: ``` GET /api/caddy/cert-status ``` -2. If the cert is expired or missing, check the host clock: `date`. If it is wrong, fix chrony (see [Domains and TLS](Admin-Domains-TLS)). +2. If the cert is expired or missing, check the host clock: `date`. If it is wrong, fix chrony — see [[Admin – Configure Domains and TLS]]. 3. For `lan` mode, clients need to trust the internal CA. Download it from the Vault page and add it to the client's trust store. -4. For `pic_ngo` / `cloudflare` / `duckdns`, port 80 and 443 must be reachable from the internet. +4. For `pic_ngo` / `cloudflare` / `duckdns`, ports 80 and 443 must be reachable from the internet. ### Domain resolves to wrong IP @@ -129,6 +137,7 @@ Check: ## Opening a shell in a container ```bash +# Run on: the cell server host, from /opt/pic make shell-api # Flask API container make shell-dns # CoreDNS container make shell-wireguard # WireGuard container (useful for wg show, ip rule list) @@ -142,14 +151,15 @@ make shell-caddy # Caddy container Inside the WireGuard container: ```bash +# Run on: the cell server host, from /opt/pic make shell-wireguard -# then: +# then, inside the container: wg show ip rule list ip route list table ``` -Connectivity tables start from 1000. Each named connection instance uses a dedicated table and fwmark. +Connectivity routing tables start from 1000. Each named connection instance uses a dedicated table and fwmark. --- @@ -158,8 +168,8 @@ Connectivity tables start from 1000. Each named connection instance uses a dedic If the cell is in an unrecoverable state and you have a backup: ```bash +# Run on: the cell server host, from /opt/pic make uninstall # stop and optionally wipe config/ and data/ -# restore from backup tar -xzf backups/cell-backup-YYYYMMDD-HHMMSS.tar.gz make start ``` @@ -167,7 +177,10 @@ make start To start completely fresh (no restore): ```bash +# Run on: the cell server host, from /opt/pic make reinstall # full wipe of config/ and data/, then setup + start ``` -`make reinstall` destroys all data. Run `make backup` first if you have anything worth keeping. +> ⚠️ **Warning:** `make reinstall` destroys all data. Run `make backup` first if you have anything worth keeping. + +Deeper: see [[User – Troubleshooting]] for end-user-facing problems to direct your users to. diff --git a/Admin-Guide.md b/Admin – Overview.md similarity index 51% rename from Admin-Guide.md rename to Admin – Overview.md index 3ea9ae6..25e61a8 100644 --- a/Admin-Guide.md +++ b/Admin – Overview.md @@ -1,4 +1,6 @@ -# Admin Guide +> **Status:** Active | **Owner:** @roof | **Updated:** 2026-06-11 + +# Admin – Overview This is the operator manual for a Personal Internet Cell. It covers everything a cell admin needs to know after the initial install. @@ -8,14 +10,14 @@ This is the operator manual for a Personal Internet Cell. It covers everything a | Page | What it covers | |---|---| -| [Setup and First Run](Admin-Setup) | The first-run wizard, cell identity, and what the installer does | -| [Domains and TLS](Admin-Domains-TLS) | Domain modes, HTTPS certificates, DDNS, and chrony | -| [Services Catalog](Admin-Services) | Installing and removing optional services; what each service provides | -| [Connectivity](Admin-Connectivity) | Named VPN/tunnel/proxy connections, per-peer routing, fail-open/fail-closed, cell-to-cell links | -| [Peers](Admin-Peers) | Adding peers, WireGuard config export, per-peer access control | -| [Backup and Restore](Admin-Backup) | What is backed up, passphrase encryption, how to restore | -| [Logging and Audit](Admin-Logging-Audit) | Per-service log levels, activity audit trail | -| [Monitoring and Troubleshooting](Admin-Monitoring-Troubleshooting) | Health checks, common errors, and fixes | +| [[Admin – Install and First Run]] | The installer, first-run wizard, cell identity, and what each step does | +| [[Admin – Configure Domains and TLS]] | Domain modes, HTTPS certificates, DDNS, and host NTP | +| [[Admin – Manage Services]] | Installing and removing optional services; what each service provides | +| [[Admin – Configure Connectivity]] | Named VPN/tunnel/proxy connections, per-peer routing, fail-open/fail-closed, cell-to-cell links | +| [[Admin – Manage Peers]] | Adding peers, WireGuard config export, per-peer access control | +| [[Admin – Back Up and Restore]] | What is backed up, passphrase encryption, how to restore | +| [[Admin – Logging and Audit]] | Per-service log levels, activity audit trail | +| [[Admin – Monitor and Troubleshoot]] | Health checks, common errors, and fixes | --- @@ -24,6 +26,7 @@ This is the operator manual for a Personal Internet Cell. It covers everything a Run these from the PIC installation directory (`/opt/pic` for installer installs): ```bash +# Run on: the cell server host, as the pic user or any user in the docker group make status # container status + API health check make logs # follow all container logs make logs-api # follow API logs @@ -38,3 +41,5 @@ make backup # archive config/ and data/ to backups/ - The Flask API (port 3000) is bound to `127.0.0.1` only. Caddy proxies all external requests. Do not expose port 3000 externally — access to it is equivalent to root access on the host. - All secrets (WireGuard keys, CA private key, admin credentials, DDNS token) live in `data/` which is git-ignored. Keep your backups safe — they contain this material. - The Docker socket is mounted only into the `cell-api` container. No other container has Docker access. + +Internals: see [[Dev – Architecture]] diff --git a/Archive – User Guide.md b/Archive – User Guide.md new file mode 100644 index 0000000..1d98f6c --- /dev/null +++ b/Archive – User Guide.md @@ -0,0 +1,13 @@ +> **Status:** Deprecated | **Owner:** @roof | **Updated:** 2026-06-11 + +> ⚠️ **DEPRECATED** — This page was a navigation stub. Its content has been folded into [[User – Start Here]] and [[User – Connect to the VPN]]. It is kept here as an archive only. + +# Archive – User Guide + +This guide was for people who had been invited to connect to someone else's Personal Internet Cell. + +The current entry point for new users is [[User – Start Here]]. + +For connecting to the VPN, see [[User – Connect to the VPN]]. + +For using installed services, see [[User – Use Your Services]]. diff --git a/Dev-API.md b/Dev – API Reference.md similarity index 97% rename from Dev-API.md rename to Dev – API Reference.md index 22e916e..24ddf67 100644 --- a/Dev-API.md +++ b/Dev – API Reference.md @@ -1,4 +1,6 @@ -# API Reference +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Dev – API Reference **Base URL:** `http://localhost:3000` (bound to 127.0.0.1; always access through Caddy in production) @@ -19,7 +21,7 @@ Session-based. Two roles: ``` POST /api/auth/login -{"username": "admin", "password": "..."} +{"username": "admin", "password": ""} ``` Returns a session cookie. All subsequent requests include the cookie. diff --git a/Dev-Architecture.md b/Dev – Architecture.md similarity index 95% rename from Dev-Architecture.md rename to Dev – Architecture.md index 8a1b74f..b48b9f7 100644 --- a/Dev-Architecture.md +++ b/Dev – Architecture.md @@ -1,4 +1,6 @@ -# Architecture +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Dev – Architecture --- @@ -65,7 +67,7 @@ Shared state in managers uses `threading.RLock`. Flask is multi-threaded and man ## Service bus -`ServiceBus` (`api/service_bus.py`) is a pub/sub system between managers. Events include `CONFIG_CHANGED`, `SERVICE_STARTED`, `SERVICE_STOPPED`. Managers subscribe to events from their dependencies (e.g., WireGuardManager subscribes to network changes). +`ServiceBus` (`api/service_bus.py`) is a pub/sub system between managers. Events include `CONFIG_CHANGED`, `SERVICE_STARTED`, `SERVICE_STOPPED`. Managers subscribe to events from their dependencies (for example, `WireGuardManager` subscribes to network changes). --- @@ -73,7 +75,7 @@ Shared state in managers uses `threading.RLock`. Flask is multi-threaded and man - Runtime config: `config/api/cell_config.json` — managed by `ConfigManager`, never edited directly - Secrets: `data/` — git-ignored; contains `auth_users.json`, WireGuard keys, DDNS token, CA key, vault secrets -- `_identity.domain` in cell config is a plain string (the domain mode, e.g. `"pic_ngo"`), not a dict +- `_identity.domain` in cell config is a plain string (the domain mode, for example `"pic_ngo"`), not a dict `ConfigManager` validates on write and keeps automatic rolling backups in `data/api/config_backups/`. @@ -109,7 +111,7 @@ Each connection is a record in `cell_config.json` under `connectivity.connection `cell_relay` connections are auto-derived from cell links that offer an exit. They have mark and table allocated but no iface or redirect_port. They are reconciled automatically on `list_connections()`. -**Migration v1 to v2:** on first `get_connectivity()` call after upgrade, `ConfigManager` calls `ConnectivityManager._migrate_connectivity_v1_to_v2()` if the stored version is less than 2. This creates one named connection per previously-configured exit type, repoints vault secret references to the new `conn__` naming, and deletes the old references. +**Migration v1 to v2:** on first `get_connectivity()` call after upgrade, `ConfigManager` calls `ConnectivityManager._migrate_connectivity_v1_to_v2()` if the stored version is less than 2. This creates one named connection per previously-configured exit type (which had fixed fwmarks `0x10`–`0x50`), repoints vault secret references to the new `conn__` naming, and deletes the old references. Peer assignments store the connection `id` as `exit_connection_id` on the peer record. The legacy `route_via` field is kept in sync for backward compatibility. diff --git a/Dev-Building-Services.md b/Dev – Build a Store Service.md similarity index 79% rename from Dev-Building-Services.md rename to Dev – Build a Store Service.md index 3b5dbcb..2a0de85 100644 --- a/Dev-Building-Services.md +++ b/Dev – Build a Store Service.md @@ -1,6 +1,8 @@ -# Building a Service +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 -This page is a summary. The full reference is the [Service Manifest Reference](Dev-Service-Manifest-Reference). +# Dev – Build a Store Service + +This page is a narrative walkthrough and submission guide. The complete field-by-field reference is [[Dev – Service Manifest Reference]]. --- @@ -49,8 +51,8 @@ Six boolean flags tell PIC which integrations to activate: When `has_subdomain` is true, provide: -- `subdomain` — the primary subdomain (e.g. `"notes"`). Results in `notes.`. -- `backend` — the `container:port` Caddy proxies to (e.g. `"cell-notes:8080"`). +- `subdomain` — the primary subdomain (for example, `"notes"`). Results in `notes.`. +- `backend` — the `container:port` Caddy proxies to (for example, `"cell-notes:8080"`). - `extra_subdomains` / `extra_backends` — additional subdomains pointing to different backends (the files service uses this for WebDAV vs Filegator). Reserved subdomains that cannot be used: `api`, `webui`, `admin`, `www`, `ns1`, `ns2`, `git`, `registry`, `install`. @@ -122,7 +124,7 @@ For `"manager": "http"`, your container must implement the account management HT - `DELETE /service-api/accounts/{username}` — delete account - `GET /service-api/accounts` — list usernames -**Note:** HTTP dispatch for the `"http"` manager is implemented in `AccountManager` (`_provision_http`/`_deprovision_http`) and is invoked from `add_peer` for any installed service whose manifest sets `accounts.manager: "http"`. The reference services (email/calendar/files) use named internal managers (`email_manager`, `calendar_manager`, `file_manager`); set `manager: "http"` to own accounts in your own container via the endpoints above. +The HTTP dispatch for the `"http"` manager is implemented in `AccountManager` (`api/account_manager.py`) via `_provision_http` / `_deprovision_http`. The reference services (email/calendar/files) use named internal managers; set `manager: "http"` to own accounts in your own container via the endpoints above. ### Egress @@ -175,8 +177,14 @@ The review checks: Increment `version` in `manifest.json` with every submission. PIC does not auto-update installed services. +--- + ## Signing and verification -Merged services are built by the two-stage pipeline (untrusted kaniko build → trivy scan → cosign sign → push), and the manifest's `image` is rewritten to a `@sha256:` digest. Cells verify the signature with cosign before starting any store container, and the default `image_verification` mode is **`enforce`** — an unsigned or undigested image will not install. While developing locally, set `image_verification.mode` to `warn` or `off` in `config/api/cell_config.json` (then restart the API container) to run images that have not been through the pipeline yet. +Merged services are built by the two-stage pipeline (untrusted kaniko build → trivy scan → cosign sign → push), and the manifest's `image` is rewritten to a `@sha256:` digest. Cells verify the signature with cosign before starting any store container. The default `image_verification` mode is `enforce` — an unsigned or undigested image will not install. -See the [Service Manifest Reference](Dev-Service-Manifest-Reference) for the complete field reference, compose template variables, the account-provisioning HTTP interface, and backup/egress integration details. +While developing locally, set `image_verification.mode` to `warn` or `off` in `config/api/cell_config.json` (then restart the API container) to run images that have not been through the pipeline yet. + +See [[ADR – 001 Isolated Build and Signing Pipeline for Store Images]] for the rationale behind the two-stage pipeline. + +See [[Dev – Service Manifest Reference]] for the complete field reference, compose template variables, the account-provisioning HTTP interface, and backup/egress integration details. diff --git a/Dev-Install-Internals.md b/Dev – Install Internals.md similarity index 92% rename from Dev-Install-Internals.md rename to Dev – Install Internals.md index 9250b3b..1a084a8 100644 --- a/Dev-Install-Internals.md +++ b/Dev – Install Internals.md @@ -1,4 +1,6 @@ -# Install Internals +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Dev – Install Internals This page describes what the installer does, the make targets, the systemd unit, and debugging options. @@ -46,6 +48,7 @@ All container operations go through `make`. The Makefile is at the project root. ### Stack lifecycle ```bash +# Run on: the cell server host, from /opt/pic (or your repo root) make start # docker compose up -d --build (full profile) make start-core # bring up only the six core containers make stop # docker compose down @@ -59,6 +62,7 @@ make shell- # shell inside container, e.g. make shell-api ### Build ```bash +# Run on: your development machine or the cell server host make build-api # rebuild cell-api image after code change make build-webui # rebuild cell-webui image after code change ``` @@ -66,6 +70,7 @@ make build-webui # rebuild cell-webui image after code change ### First install and maintenance ```bash +# Run on: the cell server host make install # generate keys, config, systemd unit; write .installed make update # git pull + rebuild + restart make reinstall # full wipe of config/ and data/, then setup + start @@ -75,6 +80,7 @@ make uninstall # stop containers; prompt to delete config/ and data/ ### Operations ```bash +# Run on: the cell server host, from /opt/pic make backup # tar config/ + data/ into backups/cell-backup-.tar.gz make restore # list available backup archives make list-peers # show peers via API @@ -86,6 +92,7 @@ make reset-admin-password # generate and set a new random admin password ### Tests ```bash +# Run on: your development machine make test # pytest unit suite make test-coverage # with coverage; htmlcov/ make test-api # API endpoint tests only @@ -124,12 +131,14 @@ If the installer cannot start chrony, it prints a warning. Proceed only after ve To see the full verbose output of every installer step: ```bash +# Run on: your Linux server, as root curl -fsSL https://install.pic.ngo | PIC_DEBUG=1 sudo -E bash ``` Or with the flag: ```bash +# Run on: your Linux server, as root curl -fsSL https://install.pic.ngo | sudo bash -s -- --debug ``` @@ -138,6 +147,7 @@ The complete log (including all subprocess output) is always at `/var/log/pic-in To debug a failing step after the installer exits: ```bash +# Run on: your Linux server sudo cat /var/log/pic-install.log ``` diff --git a/Dev-Guide.md b/Dev – Overview.md similarity index 65% rename from Dev-Guide.md rename to Dev – Overview.md index 77ae63e..0452987 100644 --- a/Dev-Guide.md +++ b/Dev – Overview.md @@ -1,6 +1,8 @@ -# Developer Guide +> **Status:** Active | **Owner:** @roof | **Updated:** 2026-06-11 -This guide is for contributors to PIC and for developers building services for the PIC service store. +# Dev – Overview + +This is the developer guide for contributors to PIC and for developers building services for the PIC service store. --- @@ -8,18 +10,19 @@ This guide is for contributors to PIC and for developers building services for t | Page | What it covers | |---|---| -| [Architecture](Dev-Architecture) | Container stack, manager pattern, service bus, data model | -| [Building a Service](Dev-Building-Services) | Manifest schema v3, compose templates, account provisioning, backup, egress | -| [API Reference](Dev-API) | Auth model, CSRF, key endpoints, connectivity v2 API | -| [Testing](Dev-Testing) | Unit tests (pytest), webui (vitest), integration, e2e, CI | -| [Install Internals](Dev-Install-Internals) | install.sh steps, make targets, systemd unit, PIC_DEBUG | +| [[Dev – Architecture]] | Container stack, manager pattern, service bus, data model, connectivity v2 | +| [[Dev – Build a Store Service]] | Manifest schema v3, compose templates, account provisioning, backup, egress | +| [[Dev – API Reference]] | Auth model, CSRF, key endpoints, connectivity v2 API | +| [[Dev – Testing]] | Unit tests (pytest), webui (vitest), integration, e2e, CI | +| [[Dev – Install Internals]] | install.sh steps, make targets, systemd unit, PIC_DEBUG | +| [[Dev – Service Manifest Reference]] | Complete field-by-field manifest reference, compose variables, HTTP account API | --- ## Quick start for local development ```bash -# Start the full stack (builds api and webui images) +# Run on: your development machine, with Docker installed git clone https://git.pic.ngo/roof/pic.git pic cd pic make start @@ -29,6 +32,7 @@ make start Run the Flask API without Docker (useful for rapid iteration): ```bash +# Run on: your development machine pip install -r api/requirements.txt python api/app.py # listens on :3000 ``` @@ -36,12 +40,14 @@ python api/app.py # listens on :3000 Run the React UI dev server (proxies `/api` to `:3000`): ```bash +# Run on: your development machine cd webui && npm install && npm run dev # listens on :5173 ``` After code changes: ```bash +# Run on: your development machine, from the repo root make build-api # rebuild only the API container make build-webui # rebuild only the webui container make restart # restart containers without rebuild @@ -70,7 +76,6 @@ tests/e2e/ Playwright UI and WireGuard tests config/ Runtime config (mostly git-ignored) data/ Runtime secrets and state (fully git-ignored) scripts/ Setup and maintenance scripts -docs/ Detailed developer documentation install.sh One-line installer Makefile All operational commands docker-compose.yml diff --git a/Dev-Service-Manifest-Reference.md b/Dev – Service Manifest Reference.md similarity index 92% rename from Dev-Service-Manifest-Reference.md rename to Dev – Service Manifest Reference.md index 08c3ec1..059754c 100644 --- a/Dev-Service-Manifest-Reference.md +++ b/Dev – Service Manifest Reference.md @@ -1,6 +1,8 @@ -# Service Manifest Reference +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 -The complete field-by-field reference for the PIC service manifest (`schema_version: 3`), the compose template variables, the account-provisioning HTTP interface, backup integration, and egress routing. For the narrative walkthrough and submission process, see [Building a Service](Dev-Building-Services). +# Dev – Service Manifest Reference + +The complete field-by-field reference for the PIC service manifest (`schema_version: 3`), the compose template variables, the account-provisioning HTTP interface, backup integration, and egress routing. For the narrative walkthrough and submission process, see [[Dev – Build a Store Service]]. **Prerequisites:** Docker, Docker Compose, basic Linux networking. You do not need to know Python to build a store service. @@ -31,13 +33,13 @@ The manifest is a JSON file with `"schema_version": 3`. The `email`, `calendar`, | Field | Type | Required | Description | |---|---|---|---| | `schema_version` | integer | yes | Must be `3`. | -| `id` | string | yes | Unique service identifier, lowercase, no spaces (e.g. `"notes"`). Must match the store index entry. | -| `name` | string | yes | Human-readable display name (e.g. `"Notes"`). | +| `id` | string | yes | Unique service identifier, lowercase, no spaces (for example, `"notes"`). Must match the store index entry. | +| `name` | string | yes | Human-readable display name (for example, `"Notes"`). | | `description` | string | yes | One-sentence description shown in the UI. | -| `version` | string | yes | Semver string for the service package itself (e.g. `"1.0.0"`). | +| `version` | string | yes | Semver string for the service package itself (for example, `"1.0.0"`). | | `author` | string | yes | Your name or organisation. | | `kind` | string | yes | Must be `"store"`. | -| `min_pic_version` | string | no | Minimum PIC version required (e.g. `"1.0"`). | +| `min_pic_version` | string | no | Minimum PIC version required (for example, `"1.0"`). | ```json { @@ -71,12 +73,12 @@ These fields are only read when `has_subdomain` is `true`. | Field | Type | Required | Description | |---|---|---|---| -| `subdomain` | string | yes (if `has_subdomain`) | The primary subdomain (e.g. `"notes"`). Results in `notes.`. Must not collide with reserved names: `api`, `webui`, `admin`, `www`, `ns1`, `ns2`, `git`, `registry`, `install`. | -| `extra_subdomains` | array of strings | no | Additional subdomains that point to the same backend (e.g. `["webmail"]`). | -| `backend` | string | yes (if `has_subdomain`) | The container-name:port combination that Caddy proxies to (e.g. `"cell-notes:8080"`). Uses Docker DNS on the `cell-network`. | +| `subdomain` | string | yes (if `has_subdomain`) | The primary subdomain (for example, `"notes"`). Results in `notes.`. Must not collide with reserved names: `api`, `webui`, `admin`, `www`, `ns1`, `ns2`, `git`, `registry`, `install`. | +| `extra_subdomains` | array of strings | no | Additional subdomains that point to the same backend (for example, `["webmail"]`). | +| `backend` | string | yes (if `has_subdomain`) | The container-name:port combination that Caddy proxies to (for example, `"cell-notes:8080"`). Uses Docker DNS on the `cell-network`. | | `extra_backends` | object | no | Maps extra subdomain names to separate backends. Key is the subdomain string; value is the backend string. The email service uses this to send `webdav.*` to a different container than `files.*`. | -**Validation at runtime:** `ServiceRegistry.get_caddy_routes()` validates all subdomain and backend values before passing them to CaddyManager or NetworkManager. Any entry whose `subdomain` does not match `^[a-z][a-z0-9-]{0,30}$`, whose `backend` does not match `^[A-Za-z0-9._-]+:\d{1,5}$`, or whose `subdomain` appears in the reserved list is silently skipped with a warning log. The same validation applies to `extra_subdomains` and `extra_backends` keys/values. For store services, this validation is also performed during installation by `ServiceStoreManager._validate_manifest()`. +**Validation at runtime:** `ServiceRegistry.get_caddy_routes()` validates all subdomain and backend values before passing them to `CaddyManager` or `NetworkManager`. Any entry whose `subdomain` does not match `^[a-z][a-z0-9-]{0,30}$`, whose `backend` does not match `^[A-Za-z0-9._-]+:\d{1,5}$`, or whose `subdomain` appears in the reserved list is silently skipped with a warning log. The same validation applies to `extra_subdomains` and `extra_backends` keys/values. For store services, this validation is also performed during installation by `ServiceStoreManager._validate_manifest()`. ### `containers` @@ -118,7 +120,7 @@ When a peer is provisioned on this service, PIC fills this template and returns | Token | Replaced with | |---|---| -| `{domain}` | The cell's public domain (e.g. `alice.pic.ngo`) | +| `{domain}` | The cell's public domain (for example, `alice.pic.ngo`) | | `{peer.username}` | The peer's username | | `{peer.service_credentials..}` | A credential value; `` is the service `id`, `` matches a name in `accounts.credentials` | | `{config.}` | A value from the merged `config_schema` result | @@ -181,7 +183,7 @@ These are validated by `ServiceStoreManager._validate_manifest()` before install | Field | Type | Required | Description | |---|---|---|---| -| `image` | string | yes | Docker image to pull. Must match the pattern `git.pic.ngo/roof/*`. Images from other registries are rejected. In the published store, the image reference is **digest-pinned** (`@sha256:...`) and **cosign-signed** by the build pipeline; under the default `enforce` verification mode, an undigested or unsigned image will not install. | +| `image` | string | yes | Docker image to pull. Must match the pattern `git.pic.ngo/roof/*`. Images from other registries are rejected. In the published store, the image reference is digest-pinned (`@sha256:...`) and cosign-signed by the build pipeline; under the default `enforce` verification mode, an undigested or unsigned image will not install. | | `container_name` | string | yes | The name Docker gives the running container. Must match `^cell-[a-z0-9][a-z0-9-]{0,30}$`. | | `volumes` | array | no | Named volumes to mount. Each entry must have `name` (the volume name) and `mount` (the absolute path inside the container). Mounts to `/`, `/etc`, `/var`, `/proc`, `/sys`, `/dev`, `/app`, `/run`, `/boot`, and paths that are a prefix of the PIC project root are forbidden. | | `env` | array | no | Environment variables to pass. Each entry has `key` and `value`. Values must match `^[A-Za-z0-9._@:/+\-= ]*$`. | @@ -198,13 +200,13 @@ When you ship a store service, you include a `compose-template.yml` alongside yo |---|---|---| | `${PIC_CFG_}` | uppercase `config_schema` key | The admin-saved value for that field, or the `default` from the schema if the admin has not set it. For example, `config_schema.port` → `${PIC_CFG_PORT}`. | | `${PIC_SECRET_}` | any name you choose | An auto-generated random secret produced by `secrets.token_urlsafe(24)` (~32 URL-safe base64 characters). Generated once on first install, then reused unchanged on every reconfigure. Stored per service in `data/service_secrets.json`. | -| `${PIC_DOMAIN}` | literal | Effective domain from `ConfigManager` (e.g. `alice.pic.ngo`). | -| `${PIC_CELL_NAME}` | literal | Cell name from the identity config (e.g. `alice`). | -| `${PIC_SERVICE_ID}` | literal | The `id` field from the service manifest (e.g. `notes`). | +| `${PIC_DOMAIN}` | literal | Effective domain from `ConfigManager` (for example, `alice.pic.ngo`). | +| `${PIC_CELL_NAME}` | literal | Cell name from the identity config (for example, `alice`). | +| `${PIC_SERVICE_ID}` | literal | The `id` field from the service manifest (for example, `notes`). | | `${SERVICE_IP}` | literal | The static IP PIC allocated from the service pool. Always set automatically. | | `${INSTANCE_ID}` | literal | For instanceable connectivity services only: the short connection-instance id, used to derive per-instance container names. | -**Volume mounts**: Because docker compose runs inside the API container but the Docker daemon runs on the host, relative volume paths in compose templates resolve relative to the compose file's directory as seen by the HOST filesystem. To avoid path resolution surprises, prefer **named volumes** for service data (Docker manages them independently). +**Volume mounts:** Because docker compose runs inside the API container but the Docker daemon runs on the host, relative volume paths in compose templates resolve relative to the compose file's directory as seen by the HOST filesystem. To avoid path resolution surprises, prefer **named volumes** for service data (Docker manages them independently). Example `compose-template.yml`: @@ -344,8 +346,8 @@ The API container only has access to `data/api/` on the host filesystem. Service | Field | Description | |---|---| -| `container` | Name of the running container to exec into (e.g. `"cell-notes"`). | -| `path` | Absolute path inside that container to archive (e.g. `"/data/notes"`). | +| `container` | Name of the running container to exec into (for example, `"cell-notes"`). | +| `path` | Absolute path inside that container to archive (for example, `"/data/notes"`). | | `name` | Archive filename stem. PIC saves the archive as `.tar.gz` under `service_data//` in the backup directory. | A service with multiple containers or multiple data directories lists one entry per directory. @@ -368,7 +370,7 @@ When `has_egress` is `true`, the cell admin can route your service's outbound tr The manifest's `egress.allowed` lists the connection **types** the admin may choose from: `default`, `wireguard_ext`, `openvpn`, `tor`, `sshuttle`, `proxy`. At assignment time the admin picks a concrete connection instance of one of those types; PIC enforces the selection with per-instance fwmarks (allocated from `0x1000` upward) and policy-routing tables (from `1000` upward) inside the `cell-wireguard` container. -Always include `default` in `allowed` so the admin has a way to use the normal path. If the chosen connection is unhealthy, traffic is dropped by the kill-switch FORWARD rule (fail-closed) unless the assignment is configured fail-open. See [Connectivity](Admin-Connectivity). +Always include `default` in `allowed` so the admin has a way to use the normal path. If the chosen connection is unhealthy, traffic is dropped by the kill-switch FORWARD rule (fail-closed) unless the assignment is configured fail-open. See [[Admin – Configure Connectivity]]. --- diff --git a/Dev-Testing.md b/Dev – Testing.md similarity index 80% rename from Dev-Testing.md rename to Dev – Testing.md index 1623035..4e0d2f3 100644 --- a/Dev-Testing.md +++ b/Dev – Testing.md @@ -1,10 +1,13 @@ -# Testing +> **Status:** Active | **Owner:** @roof | **Applies to:** main (2026-06) | **Updated:** 2026-06-11 + +# Dev – Testing --- ## Running tests ```bash +# Run on: your development machine, from the repo root make test # pytest unit tests (excludes e2e and integration) make test-coverage # with coverage; HTML report in htmlcov/ make test-api # API endpoint tests only @@ -28,20 +31,22 @@ The unit suite covers manager classes, route handlers, and utility functions. Te Important rule: when testing write-failure paths, mock `builtins.open` with `side_effect=OSError`. Do not rely on unwritable host paths — CI may run as root and can create any path. -The test count grows as features are added (3200+ as of mid-2026). Run `make test` to see the current count. +The unit suite has approximately 3,218 tests as of mid-2026 (run `make test` to see the current count). ### Integration tests ```bash +# Run on: your development machine, against a running make start stack make test-integration # full suite; modifies cell state make test-integration-readonly # read-only checks; safe to run at any time ``` -Require a running `make start` stack. These tests create peers, install services, and change configuration. Run them against a development cell, not production. +These tests create peers, install services, and change configuration. Run them against a development cell, not production. ### End-to-end tests ```bash +# Run on: your development machine make test-e2e-deps # install Playwright and browser binaries (run once) make test-e2e-api # API-level e2e tests make test-e2e-ui # Browser-level UI tests via Playwright @@ -65,6 +70,7 @@ The Playwright tests drive a real browser against a running stack. `test-e2e-ui` Gitea Actions runs the unit suite on every push using the self-hosted runner VMs (`gitea-action0` trusted, `gitea-action1` sacrificial for untrusted builds). The workflow file calls: ```bash +# Run by: Gitea Actions on the gitea-action0 runner pytest tests/ --ignore=tests/e2e --ignore=tests/integration ``` @@ -75,6 +81,7 @@ Image builds (for the email, calendar, and files service images) run on path-fil ## Webui tests ```bash +# Run on: your development machine, from the webui/ directory cd webui && npm run test # vitest unit tests ``` diff --git a/Home.md b/Home.md index 5779457..3689c2a 100644 --- a/Home.md +++ b/Home.md @@ -1,32 +1,35 @@ +> **Status:** Active | **Owner:** @roof | **Updated:** 2026-06-11 + # Personal Internet Cell -A **Personal Internet Cell** (PIC) is a self-hosted server you run on your own hardware. It gives you a private VPN, DNS, NTP, and HTTPS reverse proxy — and optionally email, calendar, contacts, and file storage — all managed from a single web interface. - -One command installs everything: - -```bash -curl -fsSL https://install.pic.ngo | sudo bash -``` - -When the installer finishes, it prints a URL. Open it in a browser and a setup wizard walks you through the rest. +A **Personal Internet Cell** ([PIC](Meta-–-Glossary)) is a small server you run on your own hardware — at home, on a spare machine, or on a cheap [VPS](Meta-–-Glossary) — that gives you private [VPN](Meta-–-Glossary), [DNS](Meta-–-Glossary), [NTP](Meta-–-Glossary), and [HTTPS](Meta-–-Glossary) without handing your data to a third party. Optional services (email, calendar, file storage) install from a built-in store and run on your hardware only. --- -## Who is this wiki for? +## Where do you want to go? -| I am... | Start here | -|---|---| -| New to self-hosting and want to know what PIC is | [Noobs — Start Here](Noobs-Start-Here) | -| A cell member who needs to connect or use services | [User Guide](User-Guide) | -| The person running a cell (the admin) | [Admin Guide](Admin-Guide) | -| A developer contributing to PIC or building a service | [Dev Guide](Dev-Guide) | +### I'm new here +Not sure what PIC is or whether it's for you? Start here. +→ [[User – Start Here]] + +### I run a cell +You administer a PIC installation and need setup, configuration, or troubleshooting help. +→ [[Admin – Overview]] + +### I work on the code +You contribute to PIC or build services for the store. +→ [[Dev – Overview]] --- -## What you get +## Quick links -- WireGuard VPN — your devices connect securely to your cell -- Private DNS and NTP for connected devices -- Automatic HTTPS certificates (Let's Encrypt or internal CA) -- Optional services installed from the built-in store: email, calendar/contacts, file storage, and connectivity exits -- A browser-based dashboard for managing everything — no SSH required for day-to-day use +- [[User – FAQ]] — common questions, short answers +- [[User – Troubleshooting]] — something isn't working +- [[Meta – Glossary]] — plain-language definitions for every term used on this wiki + +--- + +## About this wiki + +This wiki is the single source of documentation for PIC. The [project repository](https://git.pic.ngo/roof/pic) contains only `README.md`; all guides, references, and decisions live here. diff --git a/Noobs-Start-Here.md b/Noobs-Start-Here.md deleted file mode 100644 index ef931de..0000000 --- a/Noobs-Start-Here.md +++ /dev/null @@ -1,94 +0,0 @@ -# Noobs — Start Here - -## What is a Personal Internet Cell? - -A Personal Internet Cell is a small server you run at home (or on a cheap VPS). It does the things that big tech companies normally do for you — but on your own hardware, under your control. - -Concretely, it gives you: - -- **A private VPN.** Your phone, laptop, and other devices connect to your cell over an encrypted WireGuard tunnel. Traffic you want to route through your home network goes through your cell instead of a stranger's server. -- **Private DNS.** Your connected devices use your cell's DNS resolver. Nobody else sees your queries. -- **Accurate time (NTP).** Your devices synchronise their clocks from your cell. -- **HTTPS.** Every service your cell runs gets a real TLS certificate automatically. -- **Optional services.** You can install email, calendar/contacts, or file storage from the built-in service store. These run on your cell — your data does not leave your hardware. - ---- - -## Do I need to be technical? - -You need to be comfortable running a Linux server and following instructions. You do not need to edit config files by hand or write any code. Everything happens through a browser-based interface after the initial install. - ---- - -## What hardware do I need? - -Any always-on Linux machine with: - -- 2 GB+ RAM -- 10 GB+ disk -- A network connection - -A Raspberry Pi 4, an old laptop, a NUC, or a cheap VPS all work. The supported Linux distributions are Debian, Ubuntu, Fedora, RHEL, and Alpine. - ---- - -## How do I install it? - -Run this single command on your Linux machine: - -```bash -curl -fsSL https://install.pic.ngo | sudo bash -``` - -Before running any script piped through `sudo bash`, you can review it first: - -```bash -curl -fsSL https://install.pic.ngo | less -``` - -The installer runs 7 steps. It detects your OS, installs Docker and the other dependencies, creates a `pic` system user, clones the code to `/opt/pic`, generates the initial configuration, starts the core services, and waits for everything to be healthy. The whole process takes a few minutes on a typical internet connection. - -When it finishes, it prints something like: - -``` -Open your browser: http://192.168.1.10:8081/setup -``` - -Open that URL. - ---- - -## The setup wizard - -A browser-based wizard appears automatically. It asks you four things: - -1. **Cell name** — a short name like `myhome` or `alices-cell`. This becomes part of your domain name if you use the `pic.ngo` option. -2. **Domain mode** — how your cell gets an HTTPS certificate. If you are not sure, choose `pic.ngo` for internet-facing use, or `lan` for a local-only setup. -3. **Timezone** — your local timezone. -4. **Admin password** — at least 12 characters, with uppercase, lowercase, and a digit. - -Click **Complete Setup**. The wizard creates your admin account and redirects you to the login page. - -Log in with username `admin` and the password you just set. - ---- - -## What now? - -You are in the dashboard. From here you can: - -- Go to **Peers** to add your devices to the VPN — see [Connect to the VPN](User-Connect-VPN). -- Go to **Services** to install email, calendar, or file storage. -- Read the [Admin Guide](Admin-Guide) for everything else. - ---- - -## What does "split-horizon DNS" mean? - -When you connect to your cell over VPN, your domain name (e.g. `myhome.pic.ngo`) resolves to your cell's VPN address. Traffic stays inside the tunnel. When you are off the VPN, the same name resolves to your cell's public IP. You do not need to do anything — it works automatically. - ---- - -## I got stuck - -See [Monitoring and Troubleshooting](Admin-Monitoring-Troubleshooting) for common problems and fixes. diff --git a/PIC.md b/PIC.md deleted file mode 100644 index 5d08b7b..0000000 --- a/PIC.md +++ /dev/null @@ -1 +0,0 @@ -Welcome to the Wiki. \ No newline at end of file diff --git a/User-Connect-VPN.md b/User – Connect to the VPN.md similarity index 54% rename from User-Connect-VPN.md rename to User – Connect to the VPN.md index 8a23749..757f809 100644 --- a/User-Connect-VPN.md +++ b/User – Connect to the VPN.md @@ -1,6 +1,8 @@ -# Connecting to the VPN +> **Status:** Active | **Owner:** @roof | **Updated:** 2026-06-11 -Your cell admin creates a WireGuard peer configuration for you. This page explains how to get it and use it. +# User – Connect to the VPN + +Your cell admin creates a [WireGuard](Meta-–-Glossary) [peer](Meta-–-Glossary) configuration for you. This page explains how to get it and use it. --- @@ -34,13 +36,13 @@ Install the WireGuard client for your device: 2. Tap the `+` button. 3. Choose **Scan from QR code**. 4. Point your camera at the QR code your admin shows you. -5. Give the tunnel a name. +5. Give the tunnel a name (for example, `My Cell`). **On a desktop (config file):** 1. Open the WireGuard app. -2. Click **Import tunnel(s) from file** (or `Add Tunnel` on Linux). -3. Select the `.conf` file. +2. Click **Import tunnel(s) from file** (or **Add Tunnel** on Linux). +3. Select the `.conf` file your admin gave you. --- @@ -48,14 +50,16 @@ Install the WireGuard client for your device: Toggle the tunnel on. After a few seconds, the status should show **Active**. +You should now see a green indicator in the WireGuard app showing the tunnel is active. + --- ## Verifying it works Once connected: -- Open a browser and navigate to your cell's domain (your admin will tell you the address, e.g. `https://myhome.pic.ngo`). It should load over HTTPS. -- DNS names ending in `.cell` (like `api.cell`) should resolve from inside the VPN — these are internal names that only work when connected. +1. Open a browser and navigate to your cell's domain (your admin will tell you the address, for example `https://myhome.pic.ngo`). It should load over [HTTPS](Meta-–-Glossary). +2. [DNS](Meta-–-Glossary) names ending in `.cell` (like `api.cell`) should resolve from inside the [VPN](Meta-–-Glossary) — these are internal names that only work when connected. If the domain works on the VPN but not off it, that is expected — some services are only available inside the tunnel. @@ -63,22 +67,11 @@ If the domain works on the VPN but not off it, that is expected — some service ## What is split-horizon DNS? -PIC runs a split-horizon DNS configuration. This means: +PIC runs a [split-horizon DNS](Meta-–-Glossary) configuration: -- **Inside the VPN:** your cell's domain name (e.g. `myhome.pic.ngo`) resolves to the cell's internal WireGuard address. Traffic goes through the tunnel. This is more efficient and keeps traffic private. +- **Inside the VPN:** your cell's domain name (for example, `myhome.pic.ngo`) resolves to the cell's internal WireGuard address. Traffic goes through the tunnel. This is more efficient and keeps traffic private. - **Outside the VPN:** the same domain resolves to the cell's public IP. Traffic goes over the regular internet. You do not need to configure anything for this to work. It is automatic. ---- - -## Troubleshooting - -**The tunnel activates but nothing loads.** -Check that the cell is running. Ask your admin to run `make status`. - -**"Handshake did not complete" or no traffic.** -Make sure the cell's WireGuard port (default `51820/udp`) is reachable from your network. If you are behind a strict firewall, ask your admin whether an alternate connectivity method is configured. - -**The cell's domain resolves but HTTPS fails.** -The TLS certificate may still be provisioning. Wait a few minutes and try again. +Didn't work? → [[User – Troubleshooting]] diff --git a/User – Start Here.md b/User – Start Here.md new file mode 100644 index 0000000..37692e0 --- /dev/null +++ b/User – Start Here.md @@ -0,0 +1,112 @@ +> **Status:** Active | **Owner:** @roof | **Updated:** 2026-06-11 + +# User – Start Here + +## What is a Personal Internet Cell? + +A Personal Internet Cell is a small server you run at home (or on a cheap virtual server). It does the things that big tech companies normally do for you — but on your own hardware, under your control. + +Concretely, it gives you: + +- A private [VPN](Meta-–-Glossary). Your phone, laptop, and other devices connect to your cell over an encrypted [WireGuard](Meta-–-Glossary) tunnel. Traffic you want to route through your home network goes through your cell instead of a stranger's server. +- Private [DNS](Meta-–-Glossary). Your connected devices use your cell's DNS resolver. Nobody else sees your queries. +- Accurate time ([NTP](Meta-–-Glossary)). Your devices synchronise their clocks from your cell. +- [HTTPS](Meta-–-Glossary). Every service your cell runs gets a real [TLS](Meta-–-Glossary) [certificate](Meta-–-Glossary) automatically. +- Optional [store services](Meta-–-Glossary). You can install email, calendar/contacts, or file storage from the built-in service store. These run on your cell — your data does not leave your hardware. + +--- + +## Do I need to be technical? + +You need to be comfortable running a Linux server and following instructions. You do not need to edit config files by hand or write any code. Everything happens through a browser-based interface after the initial install. + +--- + +## What hardware do I need? + +Any always-on Linux machine with: + +- 2 GB or more RAM +- 10 GB or more disk +- A network connection + +A Raspberry Pi 4, an old laptop, a NUC, or a cheap VPS all work. The supported Linux distributions are Debian, Ubuntu, Fedora, RHEL, and Alpine. + +--- + +## How do I install it? + +Run this single command on your Linux machine: + +```bash +# Run on: your Linux server, as a user with sudo access +curl -fsSL https://install.pic.ngo | sudo bash +``` + +Before running any script piped through `sudo bash`, you can review it first: + +```bash +# Run on: your Linux server +curl -fsSL https://install.pic.ngo | less +``` + +The installer runs 7 steps. It detects your OS, installs [Docker](Meta-–-Glossary) and the other dependencies, creates a `pic` system user, clones the code to `/opt/pic`, generates the initial configuration, starts the [core containers](Meta-–-Glossary), and waits for everything to be healthy. The whole process takes a few minutes on a typical internet connection. + +When it finishes, it prints something like: + +``` +Open your browser: http://192.168.1.10:8081/setup +``` + +Open that URL. + +--- + +## The setup wizard + +A browser-based wizard appears automatically. It asks you four things: + +1. **Cell name** — a short name like `myhome` or `alices-cell`. This becomes part of your domain name if you use the `pic.ngo` option. +2. **Domain mode** — how your cell gets an HTTPS certificate. If you are not sure, choose `pic.ngo` for internet-facing use, or `lan` for a local-only setup. See [[Admin – Configure Domains and TLS]] for a full explanation. +3. **Timezone** — your local timezone. +4. **Admin password** — at least 12 characters, with uppercase, lowercase, and a digit. + +Click **Complete Setup**. The wizard creates your admin account and redirects you to the login page. + +Log in with username `admin` and the password you just set. + +--- + +## What now? + +You are in the dashboard. From here you can: + +- Go to **Peers** to add your devices to the VPN — see [[User – Connect to the VPN]]. +- Go to **Services** to install email, calendar, or file storage — see [[User – Use Your Services]]. +- Read [[Admin – Overview]] for everything an admin needs to do. + +--- + +## The peer dashboard (for invited users) + +If you were invited to join someone else's cell rather than running your own, you are a **peer**. Your admin creates a [WireGuard](Meta-–-Glossary) configuration file or QR code for you. Once you connect, open the cell's web address in a browser and log in with the credentials your admin gives you. + +The peer dashboard shows: + +- Your VPN connection status +- Connection info for any services the admin has set up for you (server addresses, ports, your username) + +The admin controls and settings pages are not visible to peers. + +--- + +## What is split-horizon DNS? + +[Split-horizon DNS](Meta-–-Glossary) means your cell's domain name (for example, `myhome.pic.ngo`) resolves to different addresses depending on whether you are on the VPN or not: + +- **Inside the VPN:** the name resolves to your cell's internal WireGuard address. Traffic stays inside the tunnel. +- **Outside the VPN:** the name resolves to your cell's public IP. + +You do not need to do anything — it works automatically. + +Didn't work? → [[User – Troubleshooting]] diff --git a/User-Services.md b/User – Use Your Services.md similarity index 52% rename from User-Services.md rename to User – Use Your Services.md index 3677c7e..0ecc991 100644 --- a/User-Services.md +++ b/User – Use Your Services.md @@ -1,4 +1,6 @@ -# Using Services +> **Status:** Active | **Owner:** @roof | **Updated:** 2026-06-11 + +# User – Use Your Services Optional services — email, calendar/contacts, and file storage — are installed by the cell admin. Not every cell will have all of them. Ask your admin what is available. @@ -6,9 +8,9 @@ Optional services — email, calendar/contacts, and file storage — are install ## Finding your connection details -Log in to the cell dashboard as a peer. The peer dashboard shows the connection information for every service your admin has set up for you: server hostnames, ports, your username, and your password. +Log in to the cell dashboard as a [peer](Meta-–-Glossary). The peer dashboard shows the connection information for every service your admin has set up for you: server hostnames, ports, your username, and your password. -You can also call this endpoint directly once connected: +You can also call this endpoint directly once connected to the [VPN](Meta-–-Glossary): ``` GET /api/peers//service-credentials @@ -20,7 +22,7 @@ This returns a filled-in connection info block for each service. ## Email -If email is installed, you can use any standard email client (Thunderbird, Apple Mail, K-9 Mail, etc.). +If email is installed, you can use any standard email client (Thunderbird, Apple Mail, K-9 Mail, and others). Your admin will give you: @@ -36,13 +38,13 @@ Standard ports: | IMAP | 993 | SSL/TLS | | SMTP (submission) | 587 | STARTTLS | -Use your cell's domain as the server address. Example: if your cell is `myhome.pic.ngo`, the IMAP server is `mail.myhome.pic.ngo`. +Use your cell's domain as the server address. For example, if your cell is `myhome.pic.ngo`, the IMAP server is `mail.myhome.pic.ngo`. --- ## Calendar and contacts (CalDAV / CardDAV) -If the calendar service is installed, you can use it with any CalDAV/CardDAV client (Apple Calendar, Thunderbird + Lightning, DAVx5 on Android, etc.). +If the calendar service is installed, you can use it with any CalDAV/CardDAV client (Apple Calendar, Thunderbird with Lightning, DAVx5 on Android, and others). | Protocol | URL pattern | |---|---| @@ -51,18 +53,18 @@ If the calendar service is installed, you can use it with any CalDAV/CardDAV cli Your username and password are the same as your cell login credentials for this service. -DAVx5 (Android) auto-discovery tip: enter `https://calendar./` as the base URL and DAVx5 will find your calendars and address books automatically. +DAVx5 on Android tip: enter `https://calendar./` as the base URL and DAVx5 will find your calendars and address books automatically. --- ## File storage (WebDAV) -If the files service is installed, you can mount it as a network drive or use a WebDAV client (Cyberduck, Finder on macOS, any WebDAV-capable app). +If the files service is installed, you can mount it as a network drive or use a WebDAV client (Cyberduck, Finder on macOS, or any WebDAV-capable app). | URL | `https://files./dav//` | |---|---| -Your username and password come from your peer connection info. +Your username and password come from your peer connection info (see above). A browser-based file manager may also be available at `https://files./` — ask your admin. @@ -70,4 +72,6 @@ A browser-based file manager may also be available at `https://files.