Skip to content

Latest commit

 

History

History
210 lines (162 loc) · 8.72 KB

File metadata and controls

210 lines (162 loc) · 8.72 KB

AGENTS.md

This repository contains the deployment and operating configuration for the public tunneling service at fedify.com.es.

Public repository

This repository is public. Assume that every tracked file, commit, pull request, CI log, and build artifact can be read by anyone.

Never add live credentials or private key material. This includes Cloudflare tokens, vault passwords, ACME account keys, SSH private keys, TLS private keys, decrypted vault content, and rendered configuration containing secret values. Keep operator-specific values such as account email addresses and allowlisted SSH public keys out of the repository unless the owner explicitly approves their publication. Use obvious placeholders in examples and tests.

The verified sish host public key and its fingerprint are intended to be public client trust anchors. Publishing them is required; publishing the corresponding private host key is forbidden.

Inspect staged changes before every commit. .gitignore reduces accidental additions but is not a security control. If sensitive data enters Git history, stop publishing, revoke or rotate the exposed value, and remove it from the history before continuing. Deleting it in a later commit is not sufficient.

Read first

Before changing the repository or the server, read these files in order:

  1. ARCHITECTURE.md describes the intended system and its security boundaries.
  2. PLAN.md tracks the implementation sequence and acceptance criteria.

Keep both documents current when an implementation choice changes the design or the remaining work.

Fixed decisions

  • Run sish as the tunnel server. Do not introduce tunnelto-server; its WebSocket control protocol is incompatible with the SSH-based localtunnel client.
  • Run sish directly under systemd. This deployment does not use Docker or another container runtime.
  • Configure the host with Ansible over SSH. Playbooks must be idempotent.
  • Use mise as the local command and tool-version entry point.
  • Obtain fedify.com.es and *.fedify.com.es certificates from Let's Encrypt with Certbot's Cloudflare DNS plugin.
  • Start with an authenticated private beta. Anonymous public access is a later cutover decision, not a bootstrap default.
  • Require tunnel clients to verify the pinned sish host key. Never use StrictHostKeyChecking=no for fedify.com.es.

Do not reverse one of these decisions without documenting the reason in ARCHITECTURE.md and updating PLAN.md first.

Target environment

  • Host: fedify.com.es
  • Bootstrap access: ssh root@fedify.com.es
  • Operating system: Ubuntu 26.04 LTS
  • Public IPv4 address at initial planning time: 217.154.0.35
  • DNS provider: Cloudflare
  • DNS records: apex and wildcard A records point to the VPS
  • Initial DNS mode: DNS-only, not Cloudflare-proxied

Treat these as recorded facts, not permanent assumptions. Check the live host, DNS, and upstream release metadata before applying a change.

Network contract

The intended listeners are:

Port Purpose
22/tcp Administrative OpenSSH access
2222/tcp Public sish SSH endpoint
80/tcp Public HTTP endpoint and HTTPS redirect
443/tcp Public HTTPS endpoint

Do not expose sish TCP forwarding, SNI forwarding, an admin console, or an additional listener unless the architecture and threat model are updated. Because sish 2.23.0 cannot reject every raw TCP remote-forward request, contain such listeners on loopback during the authenticated beta and require protocol-level rejection before anonymous access.

Working rules

  • Use a Cloudflare API token restricted to DNS edits for the fedify.com.es zone. Do not use a global API key.
  • Mark Ansible tasks that handle secrets with no_log: true and suppress diffs for secret-bearing templates.
  • Pin the sish version and verify the upstream checksum before installation. Do not deploy an unpinned latest artifact.
  • Keep the sish SSH host key and ACME state persistent across upgrades.
  • Publish the sish host public key only after confirming its fingerprint through authenticated administrative access and an independent channel. Do not treat unauthenticated ssh-keyscan output as a trust anchor.
  • Run sish as a dedicated unprivileged system user. Grant only CAP_NET_BIND_SERVICE so it can bind ports 80 and 443.
  • Write logs to the systemd journal unless a documented operational need calls for another sink.
  • Make file updates atomic where a partial write could break startup, especially for the sish binary, configuration, and TLS credentials. Switch a certificate and its private key through one atomic reference; do not replace the two active paths separately.
  • Point https-certificate-directory at a directory containing fedify.com.es.crt and fedify.com.es.key. sish pairs *.crt files with same-basename .key files; Certbot's fullchain.pem and privkey.pem are source files, not the deployed names.
  • Use Ansible handlers so sish restarts only when its binary, configuration, or certificates change.
  • Preserve the existing administrative SSH path during bootstrap. Allow port 22 in the firewall before enabling it, and verify a second SSH session before tightening SSH access.
  • Do not change Cloudflare records from DNS-only to proxied as a side effect of deployment work. That change affects SSH endpoint naming, TLS, request handling, and abuse controls.
  • Prefer Ansible built-in modules over shell commands. When a command is unavoidable, give it an explicit idempotence condition and a focused changed_when rule.

Repository command surface

The implementation should expose these commands through mise:

  • mise run check: validate formatting, Ansible syntax, and lint rules.
  • mise run deploy:check: show the proposed production change with Ansible check and diff mode.
  • mise run deploy: apply the production playbook.
  • mise run verify: run non-destructive checks against the deployed service.

Inspect mise.toml before invoking a task. Until a task exists, do not claim it has been run.

Deployment safety

Before a production apply:

  1. Inspect git status and the complete diff.
  2. Run the repository checks.
  3. Run mise run deploy:check and review every proposed change.
  4. Confirm that the current SSH session can survive the firewall and service changes.
  5. Apply with mise run deploy.
  6. Run mise run verify and a real end-to-end tunnel test.

An Ansible check-mode run is a preview, not proof that the apply will succeed. Certificate issuance and other external operations may need additional staging or read-only validation.

Required verification

Use checks appropriate to the changed layer. A complete deployment should cover:

  • Ansible syntax and lint checks.
  • systemd-analyze verify for the rendered unit.
  • systemctl is-active sish and recent journal inspection.
  • Listener checks for ports 22, 2222, 80, and 443.
  • Negative raw TCP forwarding checks, including a fixed port and -R 0, that prove no additional non-loopback listener is created or externally reachable.
  • Certificate hostname, chain, and expiration checks.
  • certbot renew --dry-run --run-deploy-hooks after renewal automation changes.
  • A real reverse tunnel from a separate machine, followed by an HTTPS request to the allocated subdomain.
  • A wrong-host-key test that proves SSH exits before creating a remote forward.
  • A comparison between the key presented on port 2222 and the published pin.
  • Tunnel cleanup after the SSH client exits.

Do not call the deployment complete when only the process or ports are up. The public HTTPS request must reach the local test server through the SSH tunnel.

Scope and communication

Infrastructure files and technical documentation should be written in English. Discussion with the repository owner may be in Korean. Keep commit messages in English.

The fedify.com.es service definition belongs in Fedify CLI. Fedify CLI will pass it to @hongminhee/localtunnel's openTunnel() function at runtime after this service passes its beta and soak checks. Localtunnel 0.5.0 provides strict host-key verification through Service.knownHosts; the Fedify service must populate that field because omitting it retains legacy non-strict behavior. Do not add the service to localtunnel's built-in registry or vendor either package in this repository.