mirror of
https://github.com/fscotto/infra.git
synced 2026-10-03 13:29:58 +00:00
Cut over Gitea HTTPS to Atlas with managed NPM upstream
This commit is contained in:
33
AGENTS.md
33
AGENTS.md
@@ -274,7 +274,7 @@ successfully. The first monthly scrub remains a runtime check.
|
|||||||
- [x] Design the staged Prometheus-to-Atlas Gitea migration in `docs/atlas-gitea-migration.md`.
|
- [x] Design the staged Prometheus-to-Atlas Gitea migration in `docs/atlas-gitea-migration.md`.
|
||||||
The approved topology keeps NPM on Prometheus and moves HTTPS and public SSH (TCP/2222) together;
|
The approved topology keeps NPM on Prometheus and moves HTTPS and public SSH (TCP/2222) together;
|
||||||
Gitea must run as a dedicated rootless user Quadlet on Atlas. The rootful-to-rootless data-layout
|
Gitea must run as a dedicated rootless user Quadlet on Atlas. The rootful-to-rootless data-layout
|
||||||
conversion passed an isolated restore rehearsal. No production traffic has changed.
|
conversion passed an isolated restore rehearsal. The later partial cutover is tracked below.
|
||||||
- [x] Prepare the dedicated Atlas Gitea dataset, non-login UID/GID 1101 with a separate rootless Podman
|
- [x] Prepare the dedicated Atlas Gitea dataset, non-login UID/GID 1101 with a separate rootless Podman
|
||||||
sub-ID range, and disabled user Quadlet. On 2026-10-01 the targeted Ansible run and a second idempotent
|
sub-ID range, and disabled user Quadlet. On 2026-10-01 the targeted Ansible run and a second idempotent
|
||||||
run passed; the generated unit was inactive, with no staging HTTP/SSH listener. POSIX ACLs on only the
|
run passed; the generated unit was inactive, with no staging HTTP/SSH listener. POSIX ACLs on only the
|
||||||
@@ -300,20 +300,29 @@ successfully. The first monthly scrub remains a runtime check.
|
|||||||
- [x] Install a separate opt-in final Gitea export helper on Prometheus. Its 2026-10-01 targeted
|
- [x] Install a separate opt-in final Gitea export helper on Prometheus. Its 2026-10-01 targeted
|
||||||
deployment and `bash -n` passed while Gitea and NPM stayed running. It refuses an active export
|
deployment and `bash -n` passed while Gitea and NPM stayed running. It refuses an active export
|
||||||
timer, stops only Gitea, verifies SQLite, publishes a checksum-verified Gitea-only version for
|
timer, stops only Gitea, verifies SQLite, publishes a checksum-verified Gitea-only version for
|
||||||
Atlas' existing pull, and leaves the source stopped on success; it has **not** been invoked.
|
Atlas' existing pull, and leaves the source stopped on success. It was invoked on 2026-10-02
|
||||||
|
after the export timer was stopped; version `20261002T071525Z` was pulled and verified on Atlas.
|
||||||
- [x] Prepare the Atlas final-restore gate without replacing the rehearsal: it accepts only a
|
- [x] Prepare the Atlas final-restore gate without replacing the rehearsal: it accepts only a
|
||||||
checksum-verified `gitea-cutover` export, refuses a running target, stages and validates the new
|
checksum-verified `gitea-cutover` export, refuses a running target, stages and validates the new
|
||||||
layout before replacing the marked rehearsal, and rolls back a failed swap. Synthetic success
|
layout before replacing the marked rehearsal, and rolls back a failed swap. Synthetic success
|
||||||
and rollback tests and a second idempotent rehearsal run passed on 2026-10-01; the final gate
|
and rollback tests passed on 2026-10-01. On 2026-10-02 the final gate replaced the rehearsal;
|
||||||
has **not** been invoked.
|
SQLite `quick_check`, all 33 repository `git fsck` checks, checksum and SSH host-key comparison passed.
|
||||||
- [x] Prepare, but do not activate, the Atlas LAN rootless Quadlet and Prometheus TCP/2222 socket
|
- [x] Start the rootless Atlas Gitea Quadlet and move the primary HTTPS route. On 2026-10-02 Atlas
|
||||||
proxy. NPM's two existing `gitea:3000` Proxy Hosts will resolve that name to Atlas through a
|
answered HTTP 200 through the Aegis gateway. NPM stayed on Prometheus; its variable upstream
|
||||||
managed Compose `extra_hosts` entry after the source container is removed; no NPM database edit
|
required a managed Nginx `server_proxy.conf` override because runtime DNS ignores Compose
|
||||||
is needed. The future-mode Prometheus check-run passed, both current-mode runs were idempotent,
|
`extra_hosts`. The primary public HTTPS page and API returned 200, and `git ls-remote` succeeded
|
||||||
the new systemd units passed verification, and source HTTP remained 200 on 2026-10-01. Public
|
for a representative repository after NPM restart; the Navidrome and Syncthing Proxy Hosts also
|
||||||
2222 is closed and the target remains inactive until the explicit cutover flags are enabled.
|
responded. The source
|
||||||
- [ ] After an explicit outage approval, perform the final consistent copy and HTTPS/SSH cutover,
|
Gitea container was removed from the desired Compose stack without deleting its data; the
|
||||||
then remove Gitea from Prometheus' desired stack and backup export without deleting source data.
|
Prometheus backup export timer resumed for NPM only. A post-cutover recursive ZFS snapshot and
|
||||||
|
encrypted Borg archive `atlas-20261002T073044Z` completed successfully.
|
||||||
|
- [ ] Complete public SSH/2222 and representative authenticated HTTPS/SSH clone/push validation.
|
||||||
|
Prometheus' TCP/2222 socket and firewalld rule are active and the local proxy presents the
|
||||||
|
matching Atlas host key, but Ikaros' external TCP connection timed out and no SYN reached
|
||||||
|
Prometheus `eth0` during the test. Investigate upstream/provider filtering; do not claim the
|
||||||
|
approved simultaneous HTTPS+SSH cutover complete. The secondary NPM hostname
|
||||||
|
`git.ov-ad3410.infomaniak.ch` did not resolve from Ikaros and had no generated NPM config file.
|
||||||
|
Do not restart the stale source Gitea after Atlas has accepted writes.
|
||||||
- [ ] Design and deploy Nextcloud as another explicitly temporary Atlas service before Uranus. Give it
|
- [ ] Design and deploy Nextcloud as another explicitly temporary Atlas service before Uranus. Give it
|
||||||
separate persistent application, database, and cache storage; keep credentials in Vault; publish it only
|
separate persistent application, database, and cache storage; keep credentials in Vault; publish it only
|
||||||
through NPM over the Prometheus--Aegis gateway; and define backup, upgrade, and eventual Uranus-migration
|
through NPM over the Prometheus--Aegis gateway; and define backup, upgrade, and eventual Uranus-migration
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -298,12 +298,13 @@ and Aegis (`10.0.0.2`). Their state is initialized ex novo in `/zpool/services/d
|
|||||||
`/zpool/services/data/syncthing`; no source application state is migrated. The music library at
|
`/zpool/services/data/syncthing`; no source application state is migrated. The music library at
|
||||||
`/zpool/media/music` is populated separately.
|
`/zpool/media/music` is populated separately.
|
||||||
|
|
||||||
The Gitea move from Prometheus to Atlas is staged in
|
The Gitea move from Prometheus to Atlas is tracked in
|
||||||
[`docs/atlas-gitea-migration.md`](docs/atlas-gitea-migration.md). Atlas has a dedicated dataset and
|
[`docs/atlas-gitea-migration.md`](docs/atlas-gitea-migration.md). The final consistent copy runs in
|
||||||
non-login account with an inactive rootless user Quadlet. An isolated copy from the verified
|
Atlas' dedicated dataset under a rootless user Quadlet. NPM remains on Prometheus and the primary
|
||||||
Prometheus backup passed SQLite, Git, and network-disabled
|
public HTTPS route serves Atlas. The public SSH/2222 socket works locally on Prometheus, but an
|
||||||
rootless-container checks; it is not the final cutover copy. NPM remains on Prometheus; the source
|
external connection did not reach its interface on 2026-10-02; check upstream filtering before
|
||||||
stack and public routes stay unchanged until a separately validated HTTPS and SSH cutover.
|
declaring the HTTPS+SSH cutover complete. The old Gitea data remains on Prometheus, but its container
|
||||||
|
is absent from the desired stack.
|
||||||
|
|
||||||
The separate `wireguard_overlay` role manages `wg0` between Prometheus (`10.0.0.1`) and Aegis
|
The separate `wireguard_overlay` role manages `wg0` between Prometheus (`10.0.0.1`) and Aegis
|
||||||
(`10.0.0.2`), generating private keys once on their respective hosts and exchanging only public keys
|
(`10.0.0.2`), generating private keys once on their respective hosts and exchanging only public keys
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ server_gitea_cutover_tools_enabled: false
|
|||||||
server_gitea_final_export: false
|
server_gitea_final_export: false
|
||||||
server_gitea_on_atlas: false
|
server_gitea_on_atlas: false
|
||||||
server_gitea_atlas_address: "{{ hostvars['atlas'].ansible_host }}"
|
server_gitea_atlas_address: "{{ hostvars['atlas'].ansible_host }}"
|
||||||
|
server_gitea_npm_domains: []
|
||||||
server_gitea_ssh_public_port: 2222
|
server_gitea_ssh_public_port: 2222
|
||||||
server_gitea_ssh_target_port: 2222
|
server_gitea_ssh_target_port: 2222
|
||||||
server_backup_export_source_keep: 3
|
server_backup_export_source_keep: 3
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ server_backup_export_enabled: true
|
|||||||
server_backup_export_start_timer: true
|
server_backup_export_start_timer: true
|
||||||
# Install the final-copy helper only; it is never run by a normal playbook invocation.
|
# Install the final-copy helper only; it is never run by a normal playbook invocation.
|
||||||
server_gitea_cutover_tools_enabled: true
|
server_gitea_cutover_tools_enabled: true
|
||||||
|
server_gitea_on_atlas: true
|
||||||
|
server_gitea_npm_domains:
|
||||||
|
- git.fscotto.duckdns.org
|
||||||
|
- git.ov-ad3410.infomaniak.ch
|
||||||
server_duckdns_domain: fscotto
|
server_duckdns_domain: fscotto
|
||||||
server_ssh_authorized_keys:
|
server_ssh_authorized_keys:
|
||||||
- name: ikaros
|
- name: ikaros
|
||||||
|
|||||||
59
ansible/roles/profile_server/tasks/gitea_npm_proxy.yml
Normal file
59
ansible/roles/profile_server/tasks/gitea_npm_proxy.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
- name: Validate the NPM Gitea cutover override
|
||||||
|
tags: [services, gitea_cutover]
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- server_gitea_cutover_tools_enabled | bool
|
||||||
|
- server_gitea_npm_domains | length > 0
|
||||||
|
- server_gitea_npm_domains | select('match', '^[a-zA-Z0-9.-]+$') | list | length == server_gitea_npm_domains | length
|
||||||
|
fail_msg: Declare the exact NPM Gitea hostnames before enabling the Atlas upstream.
|
||||||
|
when: server_gitea_on_atlas | bool
|
||||||
|
|
||||||
|
- name: Ensure the NPM custom configuration directory exists
|
||||||
|
tags: [services, gitea_cutover]
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /opt/npm/data/nginx/custom
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0755"
|
||||||
|
when: server_gitea_cutover_tools_enabled | bool
|
||||||
|
|
||||||
|
- name: Render the Gitea-only NPM runtime upstream override
|
||||||
|
tags: [services, gitea_cutover]
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: prometheus-gitea-npm-proxy.conf.j2
|
||||||
|
dest: /opt/npm/data/nginx/custom/server_proxy.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: server_gitea_npm_override
|
||||||
|
when: server_gitea_on_atlas | bool
|
||||||
|
|
||||||
|
- name: Remove the Gitea NPM override when source routing is selected
|
||||||
|
tags: [services, gitea_cutover]
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /opt/npm/data/nginx/custom/server_proxy.conf
|
||||||
|
state: absent
|
||||||
|
when:
|
||||||
|
- server_gitea_cutover_tools_enabled | bool
|
||||||
|
- not server_gitea_on_atlas | bool
|
||||||
|
|
||||||
|
- name: Validate NPM configuration after a Gitea upstream change
|
||||||
|
tags: [services, gitea_cutover]
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv: [podman, exec, nginx-proxy-manager, nginx, -t]
|
||||||
|
changed_when: false
|
||||||
|
when:
|
||||||
|
- server_gitea_on_atlas | bool
|
||||||
|
- server_gitea_npm_override is changed
|
||||||
|
- not ansible_check_mode
|
||||||
|
|
||||||
|
- name: Reload NPM after validating the Gitea upstream change
|
||||||
|
tags: [services, gitea_cutover]
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv: [podman, exec, nginx-proxy-manager, nginx, -s, reload]
|
||||||
|
when:
|
||||||
|
- server_gitea_on_atlas | bool
|
||||||
|
- server_gitea_npm_override is changed
|
||||||
|
- not ansible_check_mode
|
||||||
@@ -65,6 +65,9 @@
|
|||||||
- name: Import Prometheus Gitea SSH proxy tasks
|
- name: Import Prometheus Gitea SSH proxy tasks
|
||||||
ansible.builtin.import_tasks: gitea_ssh_proxy.yml
|
ansible.builtin.import_tasks: gitea_ssh_proxy.yml
|
||||||
|
|
||||||
|
- name: Import Prometheus Gitea NPM proxy override tasks
|
||||||
|
ansible.builtin.import_tasks: gitea_npm_proxy.yml
|
||||||
|
|
||||||
- name: Ensure server SSH authorized key fragments directory exists
|
- name: Ensure server SSH authorized key fragments directory exists
|
||||||
tags: [services, ssh]
|
tags: [services, ssh]
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Managed by Ansible. NPM's variable proxy upstream uses Nginx DNS, not /etc/hosts.
|
||||||
|
{% for domain in server_gitea_npm_domains %}
|
||||||
|
if ($host = {{ domain }}) {
|
||||||
|
set $server {{ server_gitea_atlas_address }};
|
||||||
|
}
|
||||||
|
{% endfor %}
|
||||||
@@ -13,10 +13,6 @@ services:
|
|||||||
- "127.0.0.1:81:81"
|
- "127.0.0.1:81:81"
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.containers.internal:host-gateway"
|
- "host.containers.internal:host-gateway"
|
||||||
{% if server_gitea_on_atlas | bool %}
|
|
||||||
# Keep both existing NPM Proxy Hosts unchanged; their gitea name now resolves to Atlas.
|
|
||||||
- "gitea:{{ server_gitea_atlas_address }}"
|
|
||||||
{% endif %}
|
|
||||||
volumes:
|
volumes:
|
||||||
- "/opt/npm/data:/data{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}"
|
- "/opt/npm/data:/data{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}"
|
||||||
- "/opt/npm/letsencrypt:/etc/letsencrypt{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}"
|
- "/opt/npm/letsencrypt:/etc/letsencrypt{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}"
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
# Gitea migration from Prometheus to Atlas
|
# Gitea migration from Prometheus to Atlas
|
||||||
|
|
||||||
This is a staged migration plan, not a cutover authorization. Keep the source
|
This records the staged migration and its observed partial cutover. Gitea is
|
||||||
Gitea, its data, both NPM Proxy Hosts, and public DNS unchanged until the
|
temporary on Atlas until Uranus; NPM remains on Prometheus. Preserve the old
|
||||||
target and rollback have been tested. Gitea is temporary on Atlas until
|
Prometheus data, but do not restart its stale Gitea after Atlas accepts writes.
|
||||||
Uranus; NPM remains on Prometheus.
|
|
||||||
|
|
||||||
## Observed source and chosen topology (2026-10-01)
|
## Observed source before cutover and chosen topology (2026-10-01)
|
||||||
|
|
||||||
- Prometheus runs the rootful `docker.gitea.com/gitea:1.25.2` image in its
|
- Prometheus runs the rootful `docker.gitea.com/gitea:1.25.2` image in its
|
||||||
managed Compose stack. `/opt/gitea/data` is about 280 MiB, uses SQLite,
|
managed Compose stack. `/opt/gitea/data` is about 280 MiB, uses SQLite,
|
||||||
@@ -108,7 +107,7 @@ not a complete Gitea recovery rehearsal from USB.
|
|||||||
## Phase 2: explicit final cutover
|
## Phase 2: explicit final cutover
|
||||||
|
|
||||||
The opt-in `/usr/local/sbin/prometheus-gitea-final-export` helper was installed
|
The opt-in `/usr/local/sbin/prometheus-gitea-final-export` helper was installed
|
||||||
on 2026-10-01 and passed `bash -n`; it has **not** been invoked. It refuses to
|
on 2026-10-01 and passed `bash -n`. It refuses to
|
||||||
run while the scheduled Prometheus export timer is active. When explicitly
|
run while the scheduled Prometheus export timer is active. When explicitly
|
||||||
triggered, it stops only the source Gitea container, checks SQLite, publishes
|
triggered, it stops only the source Gitea container, checks SQLite, publishes
|
||||||
a checksum-verified Gitea-only version for Atlas' existing pull, and leaves
|
a checksum-verified Gitea-only version for Atlas' existing pull, and leaves
|
||||||
@@ -119,26 +118,38 @@ After Atlas pulls that version, its separate
|
|||||||
`--tags gitea_final_restore -e atlas_gitea_final_restore=true` gate accepts
|
`--tags gitea_final_restore -e atlas_gitea_final_restore=true` gate accepts
|
||||||
only metadata marked `gitea-cutover`, validates a private staged replacement,
|
only metadata marked `gitea-cutover`, validates a private staged replacement,
|
||||||
and swaps it for the marked rehearsal. The swap and its rollback path passed
|
and swaps it for the marked rehearsal. The swap and its rollback path passed
|
||||||
synthetic tests on 2026-10-01; the gate has not been used on live Gitea data.
|
synthetic tests on 2026-10-01; the live gate succeeded on 2026-10-02.
|
||||||
|
|
||||||
The network change is also prepared but inactive. `server_gitea_on_atlas=true`
|
On 2026-10-02 the operator approved the outage. The final stopped-source
|
||||||
removes the rootful Gitea service from the desired Prometheus Compose stack,
|
export `20261002T071525Z` passed the Atlas pull checksum; the guarded restore
|
||||||
adds `gitea:192.168.178.55` to NPM's container hosts file, and removes Gitea
|
replaced the rehearsal. SQLite `quick_check`, all 33 repository `git fsck`
|
||||||
from future Prometheus backup exports. Both existing NPM Proxy Host records
|
checks, and the source/target SSH host-key comparison passed. The rootless
|
||||||
remain at `gitea:3000`, but that name then resolves to Atlas; no direct SQLite
|
Atlas Quadlet serves LAN HTTP/3000 and SSH/2222, reachable from Prometheus
|
||||||
edit or NPM login is required. A separate systemd socket on public TCP/2222
|
through Aegis; its firewall admits only Aegis. The final marker gates startup.
|
||||||
proxies SSH to Atlas TCP/2222 over the gateway, leaving administrative TCP/22
|
|
||||||
unchanged. Atlas' production flag changes the user Quadlet from loopback
|
|
||||||
staging ports to LAN ports 3000/2222, grants only Aegis access in firewalld,
|
|
||||||
and starts it **only** after the `.final-sha256` marker exists. Neither flag
|
|
||||||
is enabled yet. The future Prometheus configuration passed a check-run; the
|
|
||||||
installed socket units passed `systemd-analyze verify` while remaining
|
|
||||||
inactive. Source Gitea still answered HTTP 200 after preparation.
|
|
||||||
|
|
||||||
The previously agreed USB prerequisite is now met, but the final export,
|
Prometheus now runs the NPM-only Compose stack. Both NPM database records still
|
||||||
production flags, and public cutover remain uninvoked. The prepared
|
say `gitea:3000`, but Nginx evaluates this variable upstream through its
|
||||||
configuration alone does not constitute a migration; confirm a fresh outage
|
runtime DNS resolver, which **does not** use a Compose `extra_hosts` alias.
|
||||||
window before stopping the source or switching traffic.
|
The initial alias attempt returned 502. A managed `server_proxy.conf` override
|
||||||
|
sets `$server` to Atlas' IP for only the two declared Gitea domains; it passed
|
||||||
|
`nginx -t` and primary HTTPS/API returned 200 after a clean NPM restart
|
||||||
|
without the alias; a representative public `git ls-remote` also succeeded.
|
||||||
|
Navidrome and Syncthing Proxy Hosts still responded. No NPM SQLite records
|
||||||
|
or credentials were changed. The
|
||||||
|
secondary hostname `git.ov-ad3410.infomaniak.ch` did not resolve from Ikaros
|
||||||
|
and had no generated NPM config file at the time of inspection.
|
||||||
|
|
||||||
|
Prometheus' public TCP/2222 socket proxies to Atlas without changing admin
|
||||||
|
SSH/22. The local socket presents the preserved Gitea ED25519 host key, but
|
||||||
|
an external TCP/2222 connection from Ikaros timed out. During the test no SYN
|
||||||
|
reached Prometheus `eth0`; its socket and firewalld port were active. Check
|
||||||
|
upstream/provider filtering before declaring public SSH complete. Do not
|
||||||
|
restart the stale source after public HTTPS has accepted target writes.
|
||||||
|
|
||||||
|
The Prometheus export timer resumed with NPM-only paths. A recursive ZFS
|
||||||
|
snapshot at `20261002T073032Z` and encrypted Borg archive
|
||||||
|
`atlas-20261002T073044Z` captured the Atlas target after cutover; Borg exited
|
||||||
|
successfully, cleaned its temporary snapshot, and the pool was healthy.
|
||||||
|
|
||||||
1. Agree on an outage and record source/target versions, pool health, the
|
1. Agree on an outage and record source/target versions, pool health, the
|
||||||
latest backups, SSH host-key fingerprints, and both current NPM routes.
|
latest backups, SSH host-key fingerprints, and both current NPM routes.
|
||||||
@@ -157,23 +168,22 @@ window before stopping the source or switching traffic.
|
|||||||
and the target service before switching NPM.
|
and the target service before switching NPM.
|
||||||
4. Enable the public TCP/2222 socket proxy on Prometheus to Atlas over Aegis
|
4. Enable the public TCP/2222 socket proxy on Prometheus to Atlas over Aegis
|
||||||
without changing administrative TCP/22. Switch Prometheus to the desired
|
without changing administrative TCP/22. Switch Prometheus to the desired
|
||||||
NPM-only Compose stack and recreate NPM with the managed `gitea` host alias
|
NPM-only Compose stack and use the managed Gitea-only NPM runtime upstream
|
||||||
so **both** existing Proxy Hosts reach Atlas without changing their database
|
override. Do not use Compose `extra_hosts`: Nginx bypasses it for the
|
||||||
records. The old Gitea data stays intact. Do not change public DNS.
|
variable upstream. The old Gitea data stays intact. Do not change public DNS.
|
||||||
5. Test HTTPS login, representative clone/push, LFS, and public SSH clone/push
|
5. Test HTTPS login, representative clone/push, LFS, and public SSH clone/push
|
||||||
on port 2222 from outside the Atlas LAN. Record the last source write and
|
on port 2222 from outside the Atlas LAN. Record the last source write and
|
||||||
first healthy target service times; do not claim RPO/RTO without measuring.
|
first healthy target service times; do not claim RPO/RTO without measuring.
|
||||||
6. After successful traffic validation, resume the Prometheus NPM-only backup
|
6. Resume the Prometheus NPM-only backup export timer after the desired stack
|
||||||
export timer and verify its next result. Verify the next Atlas snapshot/Borg
|
is active and verify its next result. Verify the next Atlas snapshot/Borg
|
||||||
run covers Gitea and test a restored target copy. Do not delete old source
|
run covers Gitea and test a restored target copy. Do not delete old source
|
||||||
data.
|
data.
|
||||||
|
|
||||||
## Rollback gate
|
## Rollback gate
|
||||||
|
|
||||||
Before Atlas accepts writes, restore the old Compose definition (removing the
|
Before Atlas accepts writes, restore the old Compose definition and remove the
|
||||||
NPM `gitea` host alias), disable the public 2222 proxy, and restart the
|
NPM override, disable the public 2222 proxy, and restart the unchanged source
|
||||||
unchanged source Gitea if target validation
|
Gitea if target validation fails. **After Atlas accepts writes, do not blindly restart the source:** its
|
||||||
fails. **After Atlas accepts writes, do not blindly restart the source:** its
|
|
||||||
SQLite database and repositories are stale. Quiesce Atlas, capture its new
|
SQLite database and repositories are stale. Quiesce Atlas, capture its new
|
||||||
data, and decide a reverse migration or an extended outage explicitly.
|
data, and decide a reverse migration or an extended outage explicitly.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user