diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml
index 69f7d1e..8bd98f6 100644
--- a/.gitea/workflows/deploy.yml
+++ b/.gitea/workflows/deploy.yml
@@ -30,7 +30,7 @@ concurrency:
env:
API_HOST: slartibartfast.kosherinata.internal
WEB_HOST: oolon.kosherinata.internal
- API_PORT: "8081"
+ API_PORT: "22672"
SSH_OPTS: -o StrictHostKeyChecking=accept-new
jobs:
diff --git a/CLAUDE.md b/CLAUDE.md
index 72cb7d3..ca51894 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -57,7 +57,8 @@ Crypto/token logic lives in `core::auth`; the flow orchestration in `core::servi
api + worker → `slartibartfast.kosherinata.internal`; SPA → `oolon.kosherinata.internal`
(nginx serves + proxies `/v1` to the API over the mesh; TLS terminates at oolon). API
-port 8081, plain HTTP behind firewalld. See `.gitea/workflows/deploy.yml` (infra truth)
+port 22672 (registered in architecture `port-allocations.md`; deliberately not the crowded
+`8081`), plain HTTP behind firewalld. See `.gitea/workflows/deploy.yml` (infra truth)
and `script/infra-setup.sh` (one-time host prep). `Type=exec`, not `notify`, because axum
doesn't `sd_notify`.
diff --git a/asset/config/config.toml.tmpl b/asset/config/config.toml.tmpl
index 66e4b1d..17c86d9 100644
--- a/asset/config/config.toml.tmpl
+++ b/asset/config/config.toml.tmpl
@@ -7,7 +7,7 @@
# Bind the mesh-routable address so the oolon proxy can reach it. firewalld
# (newsfeed-api service) bounds who may connect; TLS terminates at oolon.
-bind = "0.0.0.0:8081"
+bind = "0.0.0.0:22672"
database_path = "/var/lib/newsfeed/newsfeed.db"
session_ttl_days = 30
diff --git a/asset/firewalld/newsfeed-api.xml b/asset/firewalld/newsfeed-api.xml
index 2bdbe56..e095257 100644
--- a/asset/firewalld/newsfeed-api.xml
+++ b/asset/firewalld/newsfeed-api.xml
@@ -3,5 +3,5 @@
newsfeed-api
newsfeed REST/JSON API. Reached over the WireGuard mesh by the oolon edge
proxy, which terminates TLS and reverse-proxies to this port.
-
+
diff --git a/asset/nginx/newsfeed.internal.conf b/asset/nginx/newsfeed.internal.conf
index 3c07638..8219b53 100644
--- a/asset/nginx/newsfeed.internal.conf
+++ b/asset/nginx/newsfeed.internal.conf
@@ -7,7 +7,7 @@
# ln -sf ../sites-available/newsfeed.internal.conf /etc/nginx/sites-enabled/
upstream newsfeed_api {
- server slartibartfast.kosherinata.internal:8081;
+ server slartibartfast.kosherinata.internal:22672;
keepalive 16;
}
diff --git a/crates/newsfeed-api/src/config.rs b/crates/newsfeed-api/src/config.rs
index 6dab44b..663e80f 100644
--- a/crates/newsfeed-api/src/config.rs
+++ b/crates/newsfeed-api/src/config.rs
@@ -30,7 +30,7 @@ pub struct Config {
impl Default for Config {
fn default() -> Self {
Self {
- bind: "127.0.0.1:8081".parse().expect("valid default bind addr"),
+ bind: "127.0.0.1:22672".parse().expect("valid default bind addr"),
database_path: PathBuf::from("/var/lib/newsfeed/newsfeed.db"),
session_ttl_days: 30,
max_db_connections: 5,
@@ -42,7 +42,7 @@ impl Default for Config {
impl Config {
/// Load configuration, layering an optional TOML file and the environment over the
- /// defaults. Env vars are `NEWSFEED_` prefixed (e.g. `NEWSFEED_BIND=0.0.0.0:8081`).
+ /// defaults. Env vars are `NEWSFEED_` prefixed (e.g. `NEWSFEED_BIND=0.0.0.0:22672`).
pub fn load(file: Option<&Path>) -> anyhow::Result {
let mut fig = Figment::from(Serialized::defaults(Config::default()));
if let Some(path) = file {
diff --git a/readme.md b/readme.md
index a44e3e6..cda8fe3 100644
--- a/readme.md
+++ b/readme.md
@@ -65,9 +65,9 @@ cd web && pnpm install && pnpm build
## Run locally
```sh
-# 1. API (creates ./data/newsfeed.db, binds 127.0.0.1:8081)
+# 1. API (creates ./data/newsfeed.db, binds 127.0.0.1:22672)
NEWSFEED_DATABASE_PATH=./data/newsfeed.db \
-NEWSFEED_BIND=127.0.0.1:8081 \
+NEWSFEED_BIND=127.0.0.1:22672 \
NEWSFEED_COOKIE_SECURE=false \
cargo run -p newsfeed-api -- --config /nonexistent
@@ -75,7 +75,7 @@ NEWSFEED_COOKIE_SECURE=false \
NEWSFEED_DATABASE_PATH=./data/newsfeed.db \
cargo run -p newsfeed-worker -- --config /nonexistent
-# 3. Frontend dev server (proxies /v1 and /health to :8081)
+# 3. Frontend dev server (proxies /v1 and /health to :22672)
cd web && pnpm dev
```
@@ -86,19 +86,19 @@ non-existent `--config` path just uses defaults + env, which is convenient for d
```sh
# register + login (cookie jar)
-curl -c cj -X POST localhost:8081/v1/auth/register -H content-type:application/json \
+curl -c cj -X POST localhost:22672/v1/auth/register -H content-type:application/json \
-d '{"username":"me","email":"me@example.com","password":"hunter2hunter2"}'
-curl -c cj -X POST localhost:8081/v1/auth/login -H content-type:application/json \
+curl -c cj -X POST localhost:22672/v1/auth/login -H content-type:application/json \
-d '{"identifier":"me","password":"hunter2hunter2"}'
# weight an interest, mint an ingest token
-curl -b cj -X PUT localhost:8081/v1/interests -H content-type:application/json -d '{"label":"rust","weight":0.9}'
-TOKEN=$(curl -b cj -X POST localhost:8081/v1/tokens -H content-type:application/json -d '{"name":"agent"}' | jq -r .secret)
+curl -b cj -X PUT localhost:22672/v1/interests -H content-type:application/json -d '{"label":"rust","weight":0.9}'
+TOKEN=$(curl -b cj -X POST localhost:22672/v1/tokens -H content-type:application/json -d '{"name":"agent"}' | jq -r .secret)
# an agent pushes a candidate; read the ranked feed
-curl -X POST localhost:8081/v1/ingest/candidates -H "authorization: Bearer $TOKEN" \
+curl -X POST localhost:22672/v1/ingest/candidates -H "authorization: Bearer $TOKEN" \
-H content-type:application/json -d '{"external_id":"a1","title":"Rust 2.0 released"}'
-curl -b cj localhost:8081/v1/feed
+curl -b cj localhost:22672/v1/feed
```
## API surface (`/v1`)
diff --git a/script/infra-setup.sh b/script/infra-setup.sh
index be43249..17947c4 100755
--- a/script/infra-setup.sh
+++ b/script/infra-setup.sh
@@ -9,7 +9,7 @@
# * a scoped /etc/sudoers.d/newsfeed_gitea_ci drop-in (visudo-verified)
# and per role:
# * API host (slartibartfast): the `newsfeed` service account, /etc/newsfeed +
-# /var/lib/newsfeed, SELinux port label for 8081, firewalld service
+# /var/lib/newsfeed, SELinux port label for 22672, firewalld service
# * WEB host (oolon): /var/www/newsfeed webroot, the internal `newsfeed.internal` TLS
# cert (lair provisioner) + step@newsfeed renewal, and the nginx vhost
#
@@ -19,7 +19,7 @@ set -euo pipefail
# --- infra truth (edit here if the topology changes) -------------------------------
API_HOST="slartibartfast.kosherinata.internal" # newsfeed-api + newsfeed-worker
WEB_HOST="oolon.kosherinata.internal" # nginx: SPA + API reverse proxy
-API_PORT="8081"
+API_PORT="22672"
CERT_NAME="newsfeed" # dot-free; serves ${CERT_NAME}.internal
PUBLIC_FQDN="rob.fyi" # WAN name (Let's Encrypt); "" to skip
CERT_EMAIL="ops@rob.fyi" # certbot registration email
diff --git a/web/vite.config.ts b/web/vite.config.ts
index 41cbb63..ed8aae3 100644
--- a/web/vite.config.ts
+++ b/web/vite.config.ts
@@ -9,8 +9,8 @@ export default defineConfig({
server: {
port: 5173,
proxy: {
- '/v1': 'http://127.0.0.1:8081',
- '/health': 'http://127.0.0.1:8081',
+ '/v1': 'http://127.0.0.1:22672',
+ '/health': 'http://127.0.0.1:22672',
},
},
build: {