This file records public, non-secret facts observed before and after production changes. It must not contain operator email addresses, SSH public keys, API tokens, private keys, Vault data, or rendered secret-bearing configuration.
The following facts were collected before the first Ansible apply:
fedify.com.esand a random wildcard name resolved to217.154.0.35.- Cloudflare nameservers
eve.ns.cloudflare.comandnolan.ns.cloudflare.comwere authoritative. The returned A records were the VPS origin address, consistent with DNS-only records. - The administrative SSH host key was already present in the operator's
trusted
known_hostsfile, and strict host-key checking succeeded. - The guest reported Ubuntu 26.04 on x86-64, kernel 7.0.0-27-generic, two CPUs, 1.8 GiB of memory, KVM virtualization, and QEMU DMI data.
- Only OpenSSH listened publicly, on TCP port 22. External probes reached port 22; ports 80, 443, and 2222 were closed or filtered.
- UFW was installed but inactive. Certbot, its Cloudflare DNS plugin, sish, Docker, nginx, and Apache were absent.
- The root filesystem had 84 GiB free.
- The guest does not expose a provider firewall API or metadata source. The provider-side rule set could not be read from the supplied SSH access, so public port reachability is checked from the operator machine before and after deployment.
- GitHub reported sish 2.23.0 as the latest release. Its Linux amd64 archive
matched the published SHA-256 value
965dec4c1a17ecc44ea0bed479f8aa841630cf411886c49047bc0646df616170.
The first bootstrap created the fedify-deploy administrative account,
installed its dedicated SSH key and sudo policy, and installed Certbot, the
Cloudflare DNS plugin, UFW, and certificate inspection tools. It did not enable
the firewall.
A new SSH session authenticated as fedify-deploy, non-interactive sudo
returned UID 0, and the production Ansible inventory completed a ping. The
original root control session remained active. A second bootstrap then added
allow rules for TCP ports 22, 2222, 80, and 443 and enabled UFW with a default
incoming deny policy. Both administrative paths still worked afterward.
An external probe reached port 22 after UFW was enabled. Ports 80, 443, and
2222 remained closed because no service listened on them yet. Reapplying the
firewall bootstrap completed with changed=0.
The first certificate attempt showed that the initial Cloudflare token could
edit DNS but could not list the zone. After the token gained Zone:Zone:Read
for fedify.com.es, the preflight query returned exactly one matching zone.
Let's Encrypt staging and production DNS-01 issuance then succeeded for the
apex and wildcard names. The production certificate is valid from July 13 to
October 11, 2026 and chains to Let's Encrypt YE1. The renewal dry run executed
the deploy hook and returned sish to the active state.
Ansible installed sish 2.23.0 under /opt/sish/releases/2.23.0. The downloaded
archive matched the recorded upstream checksum. The process runs as the sish
user with only CAP_NET_BIND_SERVICE; systemd-analyze security reported an
exposure score of 3.2. The TLS key is readable by sish but not by an unrelated
user. The Certbot timer is enabled and active.
The host key derived through authenticated administrative SSH matched the key
presented by the newly opened external port 2222. Its fingerprint is
SHA256:MS+vPYDnU2dceunPdykxErOjWoTKQG/Hcy0HFfQc6mg. The matching public key
was published in client/fedify.com.es.known_hosts. External probes reached
only the intended ports 22, 2222, 80, and 443.
The first fixed-port negative test exposed an interaction between sish 2.23.0,
port-bind-range: "0", and systemd socket-bind filtering. The denied bind made
sish retry port 0 recursively until it exhausted its stack. systemd restarted
the process after five seconds. The setting was removed while the
SocketBindAllow and SocketBindDeny rules remained in force. Repeating both
the fixed-port request and -R 0 then produced immediate SSH forwarding
failures, left no listener, and did not change the sish PID or restart count.
An allowlisted key opened an HTTPS tunnel from the operator machine to a local HTTP server. The public response matched the local file byte for byte, and port 80 redirected to the same path on HTTPS. A WebSocket client completed an echo exchange through a separate tunnel. A non-allowlisted key was rejected, and a deliberately wrong host-key pin stopped SSH before forwarding. Each public route returned 404 immediately after its SSH process exited.
The SSH client printed URLs in the form
https://<16 lowercase alphanumeric characters>.fedify.com.es, which matches
the random-subdomain configuration. A normal TLS client validated the wildcard
certificate without a bypass flag.
Staging issuance now records a persistent verification marker, so later
deployments do not request and delete a staging certificate on every run. A
full second production apply completed with changed=0. The read-only
verification playbook passed all 14 checks.
After a VPS reboot, administrative SSH returned, sish started automatically with zero restarts, and all four intended ports were externally reachable. The persistent host key still matched the repository pin and the key presented on port 2222. The verification playbook passed again. A new post-reboot HTTPS tunnel returned the local test content, redirected HTTP to HTTPS, and disappeared after the SSH process closed.