chore: purge retired git.tx1138.com registry host from the codebase

The tx1138 Gitea was retired as a release server 2026-06-13 and its registry
frontend is fully dead (500 on every /v2 manifest read, observed 2026-07-10).
Nothing may reference it anymore:

- registry.rs: no longer a default registry, no longer force-enabled on
  load; saved configs are stripped of it on load (same one-time migration
  treatment as the decommissioned Hetzner mirror), with a regression test.
- image_policy.rs: removed from TRUSTED_REGISTRIES — refs through the dead
  host are now refused at the pull site (rejection test added).
- api/handler: dropped the legacy catalog-proxy fallback URL.
- .gitmodules: indeedhub submodule repointed to the OVH Gitea.
- scripts, image-recipe, app-catalog data, neode-ui strings, docs, and all
  test fixtures repointed to 146.59.87.168:3000 (or neutral example hosts).
- image-versions.sh: ARCHY_REGISTRY_FALLBACK emptied (guarded consumers
  skip it); reconcile-containers.sh candidate guard hardened.

The only remaining occurrences of the host string are the strip/reject
enforcement paths and their regression tests — the code that guarantees it
is never used again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Dorian 2026-07-10 18:55:32 +01:00
parent 99529fcce5
commit 4b0e44fc6c
29 changed files with 140 additions and 101 deletions

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "indeedhub"]
path = indeedhub
url = https://git.tx1138.com/lfg2025/indeehub.git
url = http://146.59.87.168:3000/lfg2025/indeehub.git

View File

@ -21,7 +21,7 @@ Add an entry to `catalog.json`:
"icon": "/assets/img/app-icons/my-app.svg",
"author": "Author",
"category": "data",
"dockerImage": "git.tx1138.com/lfg2025/my-app:1.0.0",
"dockerImage": "146.59.87.168:3000/lfg2025/my-app:1.0.0",
"repoUrl": "https://github.com/...",
"containerConfig": {
"ports": ["8080:8080"],

View File

@ -172,7 +172,7 @@
"author": "File Browser",
"category": "data",
"tier": "core",
"dockerImage": "git.tx1138.com/lfg2025/filebrowser:v2.27.0",
"dockerImage": "146.59.87.168:3000/lfg2025/filebrowser:v2.27.0",
"repoUrl": "https://github.com/filebrowser/filebrowser",
"containerConfig": {
"ports": [
@ -285,7 +285,7 @@
"icon": "/assets/img/app-icons/fedimint.png",
"author": "Fedimint",
"category": "money",
"dockerImage": "git.tx1138.com/lfg2025/gatewayd:v0.10.0",
"dockerImage": "146.59.87.168:3000/lfg2025/gatewayd:v0.10.0",
"repoUrl": "https://github.com/fedimint/fedimint",
"containerConfig": {
"ports": [

View File

@ -12,7 +12,7 @@ set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FRONTEND_DIR="${INDEEHUB_FRONTEND:-$HOME/Projects/indeehub-frontend}"
VERSION="${1:-latest}"
REGISTRY="${REGISTRY:-git.tx1138.com}"
REGISTRY="${REGISTRY:-146.59.87.168:3000}"
NAMESPACE="${NAMESPACE:-lfg2025}"
IMAGE_NAME="indeedhub"
RUNTIME="${RUNTIME:-podman}"

View File

@ -126,15 +126,15 @@ impl ApiHandler {
}
/// Server-side fetch of the upstream app catalog so the browser can
/// load it without fighting CORS (git.tx1138.com emits no ACAO) or
/// load it without fighting CORS (upstream Gitea emits no ACAO) or
/// CSP (the fallback IP-port URL isn't in `connect-src`). The upstream
/// list is derived from the operator's configured container registries
/// so switching mirrors in Settings changes the App Store source too —
/// each active registry contributes one Gitea `raw/branch/main/catalog.json`
/// URL (http or https per `tls_verify`), tried in priority order.
/// If registry config can't be loaded, falls back to the legacy
/// hardcoded pair so the App Store still renders on nodes that haven't
/// persisted a registry config yet. 15s total timeout.
/// If registry config can't be loaded, falls back to the hardcoded OVH
/// URL so the App Store still renders on nodes that haven't persisted
/// a registry config yet. 15s total timeout.
async fn handle_app_catalog_proxy(&self) -> Result<Response<hyper::Body>> {
let mut upstreams: Vec<String> = Vec::new();
if let Ok(config) = crate::container::registry::load_registries(&self.config.data_dir).await
@ -155,10 +155,6 @@ impl ApiHandler {
"http://146.59.87.168:3000/lfg2025/app-catalog/raw/branch/main/catalog.json"
.to_string(),
);
upstreams.push(
"https://git.tx1138.com/lfg2025/app-catalog/raw/branch/main/catalog.json"
.to_string(),
);
}
let client = match reqwest::Client::builder()
@ -527,7 +523,7 @@ impl ApiHandler {
// App-catalog proxy — fetches catalog.json from the configured
// upstream URLs server-side so the browser doesn't hit CORS
// (git.tx1138.com has no ACAO header) or CSP (IP-port upstream
// (upstream Gitea has no ACAO header) or CSP (IP-port upstream
// falls outside `connect-src`). Session-authenticated so only
// the logged-in node owner can spin up fetches.
(Method::GET, "/api/app-catalog") => {

View File

@ -5,11 +5,12 @@
//! 1.8.0 hardening plan).
/// Registries images may be pulled from with an explicit host part.
/// (git.tx1138.com was removed 2026-07-10: the host is retired and must
/// never be pulled through again.)
pub const TRUSTED_REGISTRIES: &[&str] = &[
"docker.io",
"ghcr.io",
"localhost",
"git.tx1138.com",
"146.59.87.168:3000",
];
@ -58,13 +59,19 @@ mod tests {
"docker.io/library/nginx:1.25",
"ghcr.io/owner/app:latest",
"localhost/archy-dev:1",
"git.tx1138.com/lfg2025/x:2",
"146.59.87.168:3000/archy/bitcoin-knots:28.1",
] {
assert!(is_valid_docker_image(img), "{img} should be accepted");
}
}
#[test]
fn rejects_retired_tx1138_registry() {
// Retired 2026-07-10 — refs through the dead host must be refused
// at the pull site, not time out against it.
assert!(!is_valid_docker_image("git.tx1138.com/lfg2025/x:2"));
}
#[test]
fn accepts_docker_hub_shorthand() {
for img in ["nginx", "grafana/grafana:11.2.0", "lightninglabs/lnd:v0.18"] {

View File

@ -234,7 +234,7 @@ pub fn available_update_for_images(pinned: &str, running_image: &str) -> Option<
}
/// Extract version tag from a full image reference.
/// e.g. "git.tx1138.com/lfg2025/lnd:v0.18.4-beta" → "v0.18.4-beta"
/// e.g. "146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta" → "v0.18.4-beta"
/// Returns "latest" if no tag or tag is empty.
pub fn extract_version_from_image(image: &str) -> String {
// Split off the tag after the last colon, but only if it comes after the last slash
@ -328,11 +328,11 @@ mod tests {
#[test]
fn test_extract_version() {
assert_eq!(
extract_version_from_image("git.tx1138.com/lfg2025/lnd:v0.18.4-beta"),
extract_version_from_image("146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta"),
"v0.18.4-beta"
);
assert_eq!(
extract_version_from_image("git.tx1138.com/lfg2025/grafana:10.2.0"),
extract_version_from_image("146.59.87.168:3000/lfg2025/grafana:10.2.0"),
"10.2.0"
);
assert_eq!(
@ -340,7 +340,7 @@ mod tests {
"latest"
);
assert_eq!(
extract_version_from_image("git.tx1138.com/lfg2025/bitcoin-knots:latest"),
extract_version_from_image("146.59.87.168:3000/lfg2025/bitcoin-knots:latest"),
"latest"
);
}
@ -352,7 +352,7 @@ mod tests {
"lfg2025/lnd"
);
assert_eq!(
image_without_registry_or_tag("git.tx1138.com/lfg2025/lnd:v0.18.4-beta"),
image_without_registry_or_tag("146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta"),
"lfg2025/lnd"
);
}
@ -369,7 +369,7 @@ mod tests {
assert_eq!(
available_update_for_images(
"146.59.87.168:3000/lfg2025/nextcloud:29",
"git.tx1138.com/lfg2025/nextcloud:29",
"146.59.87.168:3000/lfg2025/nextcloud:29",
),
None
);
@ -389,7 +389,7 @@ mod tests {
#[test]
fn test_parse_image_versions() {
let content = r#"
ARCHY_REGISTRY="git.tx1138.com/lfg2025"
ARCHY_REGISTRY="146.59.87.168:3000/lfg2025"
LND_IMAGE="$ARCHY_REGISTRY/lnd:v0.18.4-beta"
GRAFANA_IMAGE="$ARCHY_REGISTRY/grafana:10.2.0"
# comment
@ -398,11 +398,11 @@ NOT_AN_IMAGE="something"
let parsed = parse_image_versions(content);
assert_eq!(
parsed.get("LND_IMAGE"),
Some(&"git.tx1138.com/lfg2025/lnd:v0.18.4-beta".to_string())
Some(&"146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta".to_string())
);
assert_eq!(
parsed.get("GRAFANA_IMAGE"),
Some(&"git.tx1138.com/lfg2025/grafana:10.2.0".to_string())
Some(&"146.59.87.168:3000/lfg2025/grafana:10.2.0".to_string())
);
assert!(!parsed.contains_key("NOT_AN_IMAGE"));
assert!(!parsed.contains_key("ARCHY_REGISTRY"));

View File

@ -2251,7 +2251,7 @@ impl ProdContainerOrchestrator {
// Reconcile recreates route through here too: an unreachable
// registry must not brick an app whose exact image:tag is
// already in local storage (boot reconcile of archy-btcpay-db
// /archy-nbxplorer with git.tx1138.com dead, 2026-07-10).
// /archy-nbxplorer with the (since-retired) upstream registry dead, 2026-07-10).
// Same exists-first semantics as
// ensure_resolved_source_available and the quadlets'
// Pull=never.
@ -4848,7 +4848,7 @@ app:
name: File Browser
version: 1.0.0
container:
image: git.tx1138.com/lfg2025/filebrowser:v2.27.0
image: 146.59.87.168:3000/lfg2025/filebrowser:v2.27.0
custom_args:
- --config
- /data/.filebrowser.json
@ -4872,7 +4872,7 @@ app:
name: LND
version: 1.0.0
container:
image: git.tx1138.com/lfg2025/lnd:v0.18.4-beta
image: 146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta
secret_env:
- key: BITCOIND_RPCPASS
secret_file: bitcoin-rpc-password
@ -4959,7 +4959,7 @@ app:
async fn install_fresh_skips_pull_when_image_local() {
// An unreachable registry must not brick a reconcile recreate whose
// exact image:tag is already in local storage (archy-btcpay-db /
// archy-nbxplorer boot reconcile with git.tx1138.com dead,
// archy-nbxplorer boot reconcile with the (since-retired) upstream registry dead,
// 2026-07-10).
let rt = Arc::new(MockRuntime::default());
rt.mark_image_present("docker.io/bitcoin/knots:28");

View File

@ -11,12 +11,17 @@ use tokio::fs;
const REGISTRY_FILE: &str = "config/registries.json";
const OVH_REGISTRY_URL: &str = "146.59.87.168:3000/lfg2025";
const TX1138_REGISTRY_URL: &str = "git.tx1138.com/lfg2025";
/// Retired registry host (release server retired 2026-06-13; the registry
/// frontend was fully dead by 2026-07-10 — 500 on every /v2 manifest read).
/// Never a default, never force-enabled; stripped from saved configs on
/// load. The literal exists ONLY so the strip can match — nothing may pull
/// through this host.
const RETIRED_TX1138_HOST: &str = "git.tx1138.com";
/// A single container registry.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Registry {
/// Registry URL (e.g., "git.tx1138.com/lfg2025" or "146.59.87.168:3000/lfg2025").
/// Registry URL (e.g., "146.59.87.168:3000/lfg2025").
pub url: String,
/// Human-readable name.
pub name: String,
@ -43,22 +48,13 @@ pub struct RegistryConfig {
impl Default for RegistryConfig {
fn default() -> Self {
Self {
registries: vec![
Registry {
url: OVH_REGISTRY_URL.to_string(),
name: "Server 1 (OVH)".to_string(),
tls_verify: false,
enabled: true,
priority: 0,
},
Registry {
url: TX1138_REGISTRY_URL.to_string(),
name: "Server 2 (tx1138)".to_string(),
tls_verify: true,
enabled: true,
priority: 10,
},
],
registries: vec![Registry {
url: OVH_REGISTRY_URL.to_string(),
name: "Server 1 (OVH)".to_string(),
tls_verify: false,
enabled: true,
priority: 0,
}],
}
}
}
@ -72,7 +68,7 @@ impl RegistryConfig {
}
/// Rewrite an image reference to use a specific registry.
/// E.g., "git.tx1138.com/lfg2025/bitcoin-knots:latest" with registry "146.59.87.168:3000/lfg2025"
/// E.g., "docker.io/lfg2025/bitcoin-knots:latest" with registry "146.59.87.168:3000/lfg2025"
/// becomes "146.59.87.168:3000/lfg2025/bitcoin-knots:latest".
pub fn rewrite_image(&self, image: &str, registry: &Registry) -> String {
// Extract the image name (last component after the org/namespace)
@ -83,7 +79,7 @@ impl RegistryConfig {
}
/// Extract the image name from a full image reference.
/// "git.tx1138.com/lfg2025/bitcoin-knots:latest" -> "bitcoin-knots:latest"
/// "146.59.87.168:3000/lfg2025/bitcoin-knots:latest" -> "bitcoin-knots:latest"
/// "docker.io/gitea/gitea:1.23" -> "gitea:1.23"
fn extract_image_name(image: &str) -> &str {
// Split by '/' and take the last segment (image:tag)
@ -118,6 +114,12 @@ pub async fn load_registries(data_dir: &Path) -> Result<RegistryConfig> {
config
.registries
.retain(|r| !r.url.contains("23.182.128.160"));
// Same treatment for the retired tx1138 registry (was Server 2 in older
// defaults): strip it on load so nothing ever pulls through the dead
// host again.
config
.registries
.retain(|r| !r.url.contains(RETIRED_TX1138_HOST));
let mut changed = config.registries.len() != before;
// Migrate: any default registry URL that isn't already in the
@ -178,12 +180,6 @@ fn force_ovh_registry_primary(config: &mut RegistryConfig) {
registry.enabled = true;
registry.priority = 0;
}
TX1138_REGISTRY_URL => {
registry.name = "Server 2 (tx1138)".to_string();
registry.tls_verify = true;
registry.enabled = true;
registry.priority = 10;
}
_ => {
if registry.priority <= 10 {
registry.priority = registry.priority.saturating_add(20);
@ -216,7 +212,7 @@ mod tests {
#[test]
fn test_extract_image_name() {
assert_eq!(
extract_image_name("git.tx1138.com/lfg2025/bitcoin-knots:latest"),
extract_image_name("146.59.87.168:3000/lfg2025/bitcoin-knots:latest"),
"bitcoin-knots:latest"
);
assert_eq!(
@ -229,11 +225,11 @@ mod tests {
#[test]
fn test_rewrite_image() {
let config = RegistryConfig::default();
// Default primary is now the OVH VPS (index 0). A tx1138-hardcoded
// image rewrites to OVH when asked for the primary mirror.
// An image hardcoded to some other registry rewrites to OVH when
// asked for the primary mirror.
let primary = &config.registries[0];
assert_eq!(
config.rewrite_image("git.tx1138.com/lfg2025/bitcoin-knots:latest", primary),
config.rewrite_image("docker.io/lfg2025/bitcoin-knots:latest", primary),
"146.59.87.168:3000/lfg2025/bitcoin-knots:latest"
);
}
@ -242,15 +238,51 @@ mod tests {
fn test_active_registries_sorted() {
let config = RegistryConfig::default();
let active = config.active_registries();
assert_eq!(active.len(), 2);
assert!(active[0].priority <= active[1].priority);
assert_eq!(active.len(), 1);
assert_eq!(active[0].url, OVH_REGISTRY_URL);
}
#[tokio::test]
async fn test_load_default() {
let tmp = TempDir::new().unwrap();
let config = load_registries(tmp.path()).await.unwrap();
assert_eq!(config.registries.len(), 2);
assert_eq!(config.registries.len(), 1);
}
#[tokio::test]
async fn test_load_strips_retired_tx1138_registry() {
// Nodes provisioned before the retirement have the tx1138 registry
// baked into their saved config (was Server 2). It must be stripped
// on load and never re-added by the defaults merge.
let tmp = TempDir::new().unwrap();
let config = RegistryConfig {
registries: vec![
Registry {
url: format!("{RETIRED_TX1138_HOST}/lfg2025"),
name: "Server 2 (tx1138)".into(),
tls_verify: true,
enabled: true,
priority: 10,
},
Registry {
url: OVH_REGISTRY_URL.into(),
name: "Server 1 (OVH)".into(),
tls_verify: false,
enabled: true,
priority: 0,
},
],
};
save_registries(tmp.path(), &config).await.unwrap();
let loaded = load_registries(tmp.path()).await.unwrap();
assert!(
!loaded
.registries
.iter()
.any(|r| r.url.contains(RETIRED_TX1138_HOST)),
"retired tx1138 registry must be stripped on load; got {:?}",
loaded.registries
);
}
#[tokio::test]
@ -266,6 +298,6 @@ mod tests {
});
save_registries(tmp.path(), &config).await.unwrap();
let loaded = load_registries(tmp.path()).await.unwrap();
assert_eq!(loaded.registries.len(), 3);
assert_eq!(loaded.registries.len(), 2);
}
}

View File

@ -2132,9 +2132,9 @@ mod tests {
fn test_manifest_origin_parses_https() {
assert_eq!(
manifest_origin(
"https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/manifest.json"
"https://releases.example.com/lfg2025/archy/raw/branch/main/releases/manifest.json"
),
Some("https://git.tx1138.com".to_string())
Some("https://releases.example.com".to_string())
);
}
@ -2151,7 +2151,7 @@ mod tests {
#[test]
fn test_manifest_origin_rejects_garbage() {
assert_eq!(manifest_origin("not a url"), None);
assert_eq!(manifest_origin("ftp://git.tx1138.com/x"), None);
assert_eq!(manifest_origin("ftp://releases.example.com/x"), None);
}
#[test]
@ -2165,7 +2165,7 @@ mod tests {
name: "archipelago".into(),
current_version: "1.7.25-alpha".into(),
new_version: "1.7.26-alpha".into(),
download_url: "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.26-alpha/archipelago".into(),
download_url: "https://releases.example.com/lfg2025/archy/raw/branch/main/releases/v1.7.26-alpha/archipelago".into(),
sha256: "x".into(),
size_bytes: 1,
blake3: None,
@ -2174,7 +2174,7 @@ mod tests {
name: "frontend".into(),
current_version: "1.7.25-alpha".into(),
new_version: "1.7.26-alpha".into(),
download_url: "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.26-alpha/frontend.tar.gz".into(),
download_url: "https://releases.example.com/lfg2025/archy/raw/branch/main/releases/v1.7.26-alpha/frontend.tar.gz".into(),
sha256: "y".into(),
size_bytes: 2,
blake3: None,
@ -2218,6 +2218,8 @@ mod tests {
label: "Server 1 (OVH)".to_string(),
},
UpdateMirror {
// Deliberately the retired host: this fixture exists to prove
// load_mirrors strips it.
url: "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/manifest.json"
.to_string(),
label: "Server 2 (tx1138)".to_string(),
@ -2406,7 +2408,7 @@ mod tests {
rollback_available: false,
schedule: UpdateSchedule::Manual,
manifest_mirror: Some(
"https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/manifest.json"
"https://releases.example.com/lfg2025/archy/raw/branch/main/releases/manifest.json"
.to_string(),
),
manifest_signed: false,

View File

@ -885,8 +885,9 @@ mod tests {
assert!(!image_uses_insecure_registry(
"23.182.128.160:3000/lfg2025/filebrowser:v2.27.0"
));
// HTTPS registries never match the insecure list.
assert!(!image_uses_insecure_registry(
"git.tx1138.com/lfg2025/bitcoin-knots:latest"
"ghcr.io/lfg2025/bitcoin-knots:latest"
));
assert!(!image_uses_insecure_registry(
"docker.io/library/nginx:latest"

View File

@ -304,7 +304,7 @@ media (latest artifact only one minor behind).
- [ ] 🟠 **Sign + checksum the ISO.** Pipeline ends at `xorriso` with no `SHA256SUMS`, no
GPG/minisign, no Secure Boot (`BOOTX64.EFI` is unsigned though `grub-efi-amd64-signed` is
installed). Emit + sign checksums; wire signed Secure Boot.
- [ ] 🟠 **Registries over HTTPS in the image too**`146.59.87.168:3000` / `git.tx1138.com`
- [ ] 🟠 **Registries over HTTPS in the image too**`146.59.87.168:3000`
are baked `insecure=true`/`tls_verify:false` (`:216`, `:2308`). (Ties to §A.)
- [ ] 🟡 **Add `unattended-upgrades` + a default-deny nftables firewall** (allow 22/80/443 +
mesh/WG). Neither exists today; OS packages drift until reflash and there is no host

View File

@ -842,7 +842,7 @@
</ul>
<h4>Registry</h4>
<ul>
<li>Private registry at <code>git.tx1138.com/lfg2025/</code></li>
<li>Private registry at <code>146.59.87.168:3000/lfg2025/</code></li>
<li>HTTPS (self-hosted Gitea)</li>
<li>All images pre-pulled into registry; nodes pull on first boot</li>
</ul>

View File

@ -65,7 +65,7 @@ origin":
### IndeeHub (the streaming target)
- Original platform (not a fork). Working source: `~/Projects/Indeedhub Prototype/`
(Vue 3 + NestJS). Submodule `git.tx1138.com/lfg2025/indeehub.git` (host retired
(Vue 3 + NestJS). Submodule `146.59.87.168:3000/lfg2025/indeehub.git` (repointed off the retired host
needs a live remote). In `archy`: image-only, `apps/indeedhub/manifest.yml` pulls
`146.59.87.168:3000/lfg2025/indeedhub:1.0.0` (+ `-api`, `-ffmpeg`, postgres, redis,
minio, nostr-rs-relay).

View File

@ -112,7 +112,7 @@ jobs:
run: |
sudo mkdir -p /etc/containers/registries.conf.d
echo '[[registry]]
location = "git.tx1138.com"
location = "146.59.87.168:3000"
insecure = true' | sudo tee /etc/containers/registries.conf.d/archipelago.conf
- name: Build unbundled ISO

View File

@ -221,7 +221,7 @@ location = "146.59.87.168:3000"
insecure = true
[[registry]]
location = "git.tx1138.com"
location = "146.59.87.168:3000"
insecure = true
REGCONF
fi
@ -1158,7 +1158,7 @@ fi
# If built against a newer GLIBC, the binary will fail at runtime.
# Rebuild with: FROM debian:13 AS builder
echo " Extracting NostrVPN binary..."
_NVPN_IMG="${NOSTR_VPN_IMAGE:-git.tx1138.com/lfg2025/nostr-vpn:v0.3.7}"
_NVPN_IMG="${NOSTR_VPN_IMAGE:-146.59.87.168:3000/lfg2025/nostr-vpn:v0.3.7}"
NVPN_IMAGE_ID="$($CONTAINER_CMD images -q "$_NVPN_IMG" 2>/dev/null)"
if [ -z "$NVPN_IMAGE_ID" ]; then
$CONTAINER_CMD pull "$_NVPN_IMG" 2>/dev/null || true
@ -1189,11 +1189,11 @@ fi
# Extract nostr-rs-relay binary from container image (native system service for VPN signaling)
echo " Extracting nostr-rs-relay binary..."
RELAY_IMAGE="$($CONTAINER_CMD images -q git.tx1138.com/lfg2025/nostr-rs-relay:0.9.0 2>/dev/null)"
RELAY_IMAGE="$($CONTAINER_CMD images -q 146.59.87.168:3000/lfg2025/nostr-rs-relay:0.9.0 2>/dev/null)"
if [ -z "$RELAY_IMAGE" ]; then
$CONTAINER_CMD pull git.tx1138.com/lfg2025/nostr-rs-relay:0.9.0 2>/dev/null || true
$CONTAINER_CMD pull 146.59.87.168:3000/lfg2025/nostr-rs-relay:0.9.0 2>/dev/null || true
fi
RELAY_CONTAINER=$($CONTAINER_CMD create git.tx1138.com/lfg2025/nostr-rs-relay:0.9.0 2>/dev/null) || true
RELAY_CONTAINER=$($CONTAINER_CMD create 146.59.87.168:3000/lfg2025/nostr-rs-relay:0.9.0 2>/dev/null) || true
if [ -n "$RELAY_CONTAINER" ]; then
$CONTAINER_CMD cp "$RELAY_CONTAINER:/usr/local/bin/nostr-rs-relay" "$ARCH_DIR/bin/nostr-rs-relay" 2>/dev/null && \
chmod +x "$ARCH_DIR/bin/nostr-rs-relay" && \
@ -2319,7 +2319,7 @@ location = "146.59.87.168:3000"
insecure = true
[[registry]]
location = "git.tx1138.com"
location = "146.59.87.168:3000"
insecure = true
REGCONF
chown -R 1000:1000 /mnt/target/home/archipelago/.config
@ -2330,7 +2330,7 @@ cat > /mnt/target/var/lib/archipelago/config/registries.json <<'DYNREG'
{
"registries": [
{"url": "146.59.87.168:3000/lfg2025", "name": "Archipelago Primary", "tls_verify": false, "enabled": true, "priority": 0},
{"url": "git.tx1138.com/lfg2025", "name": "Archipelago Fallback", "tls_verify": true, "enabled": true, "priority": 10}
{"url": "146.59.87.168:3000/lfg2025", "name": "Archipelago Fallback", "tls_verify": true, "enabled": true, "priority": 10}
]
}
DYNREG
@ -2475,7 +2475,7 @@ if [ -d "$REPO_DIR/.git" ]; then
exit 0 # Already cloned
fi
echo "[update] Cloning Archipelago repo for self-updates..."
su - archipelago -c "git clone https://git.tx1138.com/lfg2025/archy $REPO_DIR" 2>/dev/null || {
su - archipelago -c "git clone https://146.59.87.168:3000/lfg2025/archy $REPO_DIR" 2>/dev/null || {
echo "[update] Git clone failed (network?). Updates will retry on next boot."
exit 0
}

View File

@ -40,10 +40,10 @@ EOF
# Configure registries (use Docker Hub and quay.io)
mkdir -p /home/archipelago/.config/containers/registries.conf.d
cat > /home/archipelago/.config/containers/registries.conf <<EOF
unqualified-search-registries = ["docker.io", "ghcr.io", "quay.io", "git.tx1138.com"]
unqualified-search-registries = ["docker.io", "ghcr.io", "quay.io", "146.59.87.168:3000"]
[[registry]]
location = "git.tx1138.com"
location = "146.59.87.168:3000"
insecure = true
EOF

View File

@ -172,7 +172,7 @@
"author": "File Browser",
"category": "data",
"tier": "core",
"dockerImage": "git.tx1138.com/lfg2025/filebrowser:v2.27.0",
"dockerImage": "146.59.87.168:3000/lfg2025/filebrowser:v2.27.0",
"repoUrl": "https://github.com/filebrowser/filebrowser",
"containerConfig": {
"ports": [
@ -285,7 +285,7 @@
"icon": "/assets/img/app-icons/fedimint.png",
"author": "Fedimint",
"category": "money",
"dockerImage": "git.tx1138.com/lfg2025/gatewayd:v0.10.0",
"dockerImage": "146.59.87.168:3000/lfg2025/gatewayd:v0.10.0",
"repoUrl": "https://github.com/fedimint/fedimint",
"containerConfig": {
"ports": [

View File

@ -348,7 +348,7 @@
<div class="mt-5 rounded-xl border border-white/10 bg-white/[0.04] p-4 text-sm text-white/65">
<p class="font-medium text-white/80 mb-2">Easy sources</p>
<p>Use images from Docker Hub, GHCR, git.tx1138.com, the VPS2 Gitea registry, or localhost. Good first candidates: Excalidraw, Stirling PDF, FreshRSS, Wallabag, HedgeDoc, CyberChef, Mealie, or PairDrop.</p>
<p>Use images from Docker Hub, GHCR, the VPS2 Gitea registry (146.59.87.168:3000), or localhost. Good first candidates: Excalidraw, Stirling PDF, FreshRSS, Wallabag, HedgeDoc, CyberChef, Mealie, or PairDrop.</p>
</div>
<div class="mt-5 flex gap-3">

View File

@ -24,7 +24,7 @@ const CATALOG_TTL = 60 * 60 * 1000 // 1 hour cache
/** Catalog URLs tried in order. First success wins.
* Primary is the backend proxy (`/api/app-catalog`) server-side fetch
* bypasses CORS on git.tx1138.com and CSP restrictions on the IP-port
* bypasses CORS on the upstream Gitea and CSP restrictions on the IP-port
* fallback. If the backend is offline (mid-restart etc.) we fall back
* to the static copy baked into the frontend build. */
const CATALOG_URLS = [

View File

@ -1405,7 +1405,7 @@ init()
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
<p>Updates survive network hiccups. Downloads now resume from exactly where a dropped connection left off, and retry up to 6 times with increasing gaps between attempts, instead of restarting from byte zero or giving up.</p>
<p>The download progress bar now shows real progress. Instead of a fake number that creeps to 95% and freezes, you see the actual bytes arriving, and it continues to update correctly even if you navigate away and come back.</p>
<p>Update check itself retries on slow responses. If git.tx1138.com is momentarily overloaded, the node tries three times with a five-second wait between attempts before concluding you're up to date.</p>
<p>Update check itself retries on slow responses. If the release server is momentarily overloaded, the node tries three times with a five-second wait between attempts before concluding you're up to date.</p>
</div>
</div>
<!-- v1.7.14-alpha -->
@ -1591,7 +1591,7 @@ init()
<span class="text-xs text-white/40">Apr 11, 2026</span>
</div>
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
<p>Migrated container registry to git.tx1138.com</p>
<p>Migrated container registry to the self-hosted Gitea</p>
</div>
</div>
<!-- v1.3.4 -->

View File

@ -78,7 +78,7 @@ if $DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -q '^electrumx$'; then
-e "DAEMON_URL=http://${RPC_USER}:${RPC_PASS}@bitcoin-knots:8332/" \
-e COIN=Bitcoin -e DB_DIRECTORY=/data \
-e "SERVICES=tcp://:50001,rpc://0.0.0.0:8000" \
"${ELECTRUMX_IMAGE:-git.tx1138.com/lfg2025/electrumx:v1.18.0}"
"${ELECTRUMX_IMAGE:-146.59.87.168:3000/lfg2025/electrumx:v1.18.0}"
fi
# Mempool API
@ -98,7 +98,7 @@ if $DOCKER ps -a --format '{{.Names}}' 2>/dev/null | grep -q '^mempool-api$'; th
-e "DATABASE_ENABLED=true" -e "DATABASE_HOST=archy-mempool-db" \
-e "DATABASE_DATABASE=mempool" -e "DATABASE_USERNAME=mempool" \
-e "DATABASE_PASSWORD=$(cat "$SECRETS_DIR/mempool-db-password" 2>/dev/null || echo mempoolpass)" \
"${MEMPOOL_API_IMAGE:-git.tx1138.com/lfg2025/mempool-api:v3.2.0}"
"${MEMPOOL_API_IMAGE:-146.59.87.168:3000/lfg2025/mempool-api:v3.2.0}"
fi
# Stop Tor tunnel if it was active

View File

@ -74,7 +74,7 @@ mkdir -p "$BUILD_DIR"
# Create Dockerfile
cat > "$BUILD_DIR/Dockerfile" << 'EOF'
FROM ${NGINX_ALPINE_IMAGE:-git.tx1138.com/lfg2025/nginx:1.29.6-alpine}
FROM ${NGINX_ALPINE_IMAGE:-146.59.87.168:3000/lfg2025/nginx:1.29.6-alpine}
# Copy the static UI
COPY index.html /usr/share/nginx/html/

View File

@ -146,7 +146,7 @@ run_smoke_tests() {
# Test 3: Install a lightweight container (filebrowser — small, fast, no deps)
TESTS=$((TESTS + 1))
local install_img="git.tx1138.com/lfg2025/filebrowser:v2.27.0"
local install_img="146.59.87.168:3000/lfg2025/filebrowser:v2.27.0"
# Check if already installed
local fb_state
fb_state=$(ssh $SSH_OPTS "$SSH_HOST" "podman inspect filebrowser --format '{{.State.Status}}' 2>/dev/null || echo 'none'")

View File

@ -9,7 +9,7 @@
#
# Image versions: sourced from /opt/archipelago/image-versions.sh (single source of truth).
# All container image references use the $*_IMAGE variables defined there.
# Images pull from the Archipelago app registry (git.tx1138.com/lfg2025/).
# Images pull from the Archipelago app registry (146.59.87.168:3000/lfg2025/).
#
# --- PLANNED REFACTOR (post-beta) ---
# This script is ~995 lines and should be split into a modular library.

View File

@ -11,7 +11,8 @@
# Archipelago app registries (primary + fallback)
ARCHY_REGISTRY="146.59.87.168:3000/lfg2025"
ARCHY_REGISTRY_FALLBACK="git.tx1138.com/lfg2025"
# No fallback registry: the old tx1138 registry host was retired (2026-06-13); empty disables the fallback path.
ARCHY_REGISTRY_FALLBACK=""
# Bitcoin stack
BITCOIN_KNOTS_IMAGE="$ARCHY_REGISTRY/bitcoin-knots:latest"

View File

@ -304,7 +304,7 @@ resolve_spec_image() {
"${ARCHY_REGISTRY_FALLBACK:-}/${image_path}" \
"80.71.235.15:3000/archipelago/${image_name}:${image_tag}" \
"80.71.235.15:3000/lfg2025/${image_name}:${image_tag}"; do
[ "$candidate" = "/" ] && continue
case "$candidate" in /*) continue;; esac
if image_exists "$candidate"; then
info "$SPEC_NAME — using local image alias $candidate"
SPEC_IMAGE="$candidate"

View File

@ -1,5 +1,5 @@
#!/bin/bash
# Self-update: pull latest code from git.tx1138.com and apply
# Self-update: pull latest code from the OVH Gitea (146.59.87.168:3000) and apply
# Designed to run on installed Archipelago nodes (as archipelago user)
#
# Usage:
@ -8,7 +8,7 @@
# ./self-update.sh --force # Apply even if already up to date
#
# The script:
# 1. Pulls latest code from origin (git.tx1138.com)
# 1. Pulls latest code from origin (146.59.87.168:3000)
# 2. Builds the Rust backend (release mode)
# 3. Builds the Vue frontend (production mode)
# 4. Installs the new binary and web UI
@ -69,7 +69,7 @@ done
# Ensure repo exists
if [ ! -d "$REPO_DIR/.git" ]; then
err "Repo not found at $REPO_DIR"
err "Clone it first: git clone https://git.tx1138.com/lfg2025/archy ~/archy"
err "Clone it first: git clone http://146.59.87.168:3000/lfg2025/archy ~/archy"
exit 1
fi

View File

@ -86,7 +86,7 @@ else
# Check trusted registry
TRUSTED=false
for reg in "docker.io" "ghcr.io" "quay.io" "registry.hub.docker.com" "git.tx1138.com"; do
for reg in "docker.io" "ghcr.io" "quay.io" "registry.hub.docker.com" "146.59.87.168:3000"; do
if echo "$IMAGE" | grep -q "$reg"; then
TRUSTED=true
break