@celilo/e2e 0.9.3 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/cpanel-host/cpanel-host-ca.crt +20 -0
- package/config/cpanel-host/docroot/.htaccess +14 -0
- package/config/cpanel-host/docroot/cms.html +4 -0
- package/config/cpanel-host/site-tls.crt +20 -0
- package/config/cpanel-host/site-tls.key +28 -0
- package/config/cpanel-host/site.conf +27 -0
- package/config/dns/com.zone +7 -0
- package/config/dns/knot-namecheap.conf +6 -0
- package/config/dns/tangohost.com.zone +14 -0
- package/config/resolver/unbound.conf +26 -0
- package/config/routing/fw-ext-routes.sh +16 -1
- package/config/routing/management-routes.sh +14 -4
- package/config/routing/minio-startup.sh +9 -0
- package/config/routing/public-sim-entrypoint.sh +24 -0
- package/config/routing/resolver-internal-routes.sh +10 -0
- package/docker/Dockerfile.apt-repo-sim +8 -0
- package/docker/Dockerfile.cpanel-host-sim +75 -0
- package/docker/Dockerfile.firewall +12 -0
- package/docker/Dockerfile.management +6 -0
- package/docker/Dockerfile.minio +7 -0
- package/docker/Dockerfile.npm-registry-sim +8 -0
- package/docker/Dockerfile.observer +11 -0
- package/docker/Dockerfile.registry +8 -0
- package/docker/Dockerfile.signal-cli +60 -0
- package/docker/Dockerfile.signal-release +44 -0
- package/docker/Dockerfile.signal-sim +17 -0
- package/docker/Dockerfile.target-machine +9 -0
- package/package.json +3 -3
- package/registry-server/package.json +17 -0
- package/registry-server/src/auth.test.ts +76 -0
- package/registry-server/src/auth.ts +105 -0
- package/registry-server/src/bootstrap-packaging.test.ts +71 -0
- package/registry-server/src/bootstrap.ts +250 -0
- package/registry-server/src/index.ts +16 -0
- package/registry-server/src/introspection.test.ts +247 -0
- package/registry-server/src/introspection.ts +204 -0
- package/registry-server/src/landing.ts +90 -0
- package/registry-server/src/module-owner-store.test.ts +85 -0
- package/registry-server/src/module-owner-store.ts +108 -0
- package/registry-server/src/rate-limit.test.ts +62 -0
- package/registry-server/src/rate-limit.ts +83 -0
- package/registry-server/src/scoped-token-store.test.ts +93 -0
- package/registry-server/src/scoped-token-store.ts +110 -0
- package/registry-server/src/server.test.ts +771 -0
- package/registry-server/src/server.ts +701 -0
- package/registry-server/src/storage.test.ts +148 -0
- package/registry-server/src/storage.ts +150 -0
- package/registry-server/src/validation.test.ts +86 -0
- package/registry-server/src/validation.ts +60 -0
- package/registry-server/tsconfig.json +15 -0
- package/scripts/stage-libsignal.ts +116 -0
- package/simulators/signal-cli/server.ts +328 -0
- package/src/cli/build.ts +7 -0
- package/src/cli/index.ts +6 -0
- package/src/container-manager.ts +47 -10
- package/src/docker-compose-generator.ts +120 -16
- package/src/exit-cleanup.test.ts +56 -0
- package/src/index.ts +7 -0
- package/src/network-builder.ts +66 -0
- package/src/public-sim-routes.test.ts +117 -0
- package/src/simulator-ips.ts +9 -0
- package/src/types.ts +71 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIDMzCCAhugAwIBAgIUNwg2dEjTZomtYfUlMacwvA348c4wDQYJKoZIhvcNAQEL
|
|
3
|
+
BQAwKDEmMCQGA1UEAwwdY2VsaWxvIGUyZSBjUGFuZWwtaG9zdCBzaW0gQ0EwIBcN
|
|
4
|
+
MjYwNzI5MTI1MDM3WhgPMjEyNjA3MDUxMjUwMzdaMCgxJjAkBgNVBAMMHWNlbGls
|
|
5
|
+
byBlMmUgY1BhbmVsLWhvc3Qgc2ltIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
|
6
|
+
MIIBCgKCAQEAqCdcXJ1jCLtUBVTH/Tu9VMhGnVjWy6UL5s99zprxxH09u23UWwAa
|
|
7
|
+
Ya48BIBbS25bv9YinLfWo5BtL7fOtZYNw3LpWSYi6NRAyUldt9mDOQ0jufQRZs5E
|
|
8
|
+
3HiRRIdHKF5ABQRTM7toMWFW6X7kTSH4ySJqQUtXThf/9C4bca8dDLNwIt+3HMfq
|
|
9
|
+
9vLP7uobTtNkasNZhmpKePtU5U90igwF04bOKF51nvTBABpuK/MrSOVXFjpabsrl
|
|
10
|
+
LHy7dG0I2J3C//N++qeBpXqEO1O7r9rcGN97FV7s5IM1TF0s/JPnztqt7mgiXYQf
|
|
11
|
+
bFAQ91Wrog2ROSecAxaXG/T2SrpTzVkrKQIDAQABo1MwUTAdBgNVHQ4EFgQUkib0
|
|
12
|
+
DPU9hPj3xiY5hHjHcgq/bNcwHwYDVR0jBBgwFoAUkib0DPU9hPj3xiY5hHjHcgq/
|
|
13
|
+
bNcwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAdbGBHyoCoaAC
|
|
14
|
+
mIM8VMjWBUwC6lPiPsrKXidym6AH1Sz446ZUje+q/h1NSeNx6hRpW92gY8AYylmN
|
|
15
|
+
cnzs6fB2cibToxxIQM1IgdGdjRBHvyJKjDOC9oWrRxuzEqoDtM3IFIO0rWmW8ubF
|
|
16
|
+
ouxakB1EAm9Lg+I7ZfljGjK7lhdPOnUPcciNR4TguDyeNFzUIvI9Ajc4HDgnom41
|
|
17
|
+
8lJ7kgYFiyVsThKXGalO2RphjGJ9mdF4UzQnukJQZSe+tsFhREsZtUFFAApZy6QF
|
|
18
|
+
XdC33NNtDAOPH/iYL1E+t2E50t1NfC6z7keiBPFzfWVeNGr6dGko7xZlr5YkSCym
|
|
19
|
+
++fPX7Ivrg==
|
|
20
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# BEGIN WordPress
|
|
2
|
+
# The stock WordPress front-controller rules, verbatim in shape: any request
|
|
3
|
+
# that is NOT a real file and NOT a real directory is handed to the CMS. A
|
|
4
|
+
# published subfolder (e.g. /nexus/) IS a real directory, so it is served from
|
|
5
|
+
# disk and never reaches the CMS — which is exactly what external_web relies on.
|
|
6
|
+
<IfModule mod_rewrite.c>
|
|
7
|
+
RewriteEngine On
|
|
8
|
+
RewriteBase /
|
|
9
|
+
RewriteRule ^index\.php$ - [L]
|
|
10
|
+
RewriteCond %{REQUEST_FILENAME} !-f
|
|
11
|
+
RewriteCond %{REQUEST_FILENAME} !-d
|
|
12
|
+
RewriteRule . /cms.html [L]
|
|
13
|
+
</IfModule>
|
|
14
|
+
# END WordPress
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIDPzCCAiegAwIBAgIUBUnN9NoJfptkeic1uhSMmvr/KskwDQYJKoZIhvcNAQEL
|
|
3
|
+
BQAwKDEmMCQGA1UEAwwdY2VsaWxvIGUyZSBjUGFuZWwtaG9zdCBzaW0gQ0EwIBcN
|
|
4
|
+
MjYwNzI5MTI1MDM3WhgPMjEyNjA3MDUxMjUwMzdaMBgxFjAUBgNVBAMMDXRhbmdv
|
|
5
|
+
aG9zdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXAn3dqIFu
|
|
6
|
+
MjApQp1HL+V3O6rTxgH5Z+0x3PqFegGDD1sPR1FNj9X5WfG7cipZgvQsjVI8xE/b
|
|
7
|
+
8j9BDLyUdhyIiDiDGnz4goGE45t6n3kN9llaOLHEvPliZSx/XuCseu6LbzwMGJc6
|
|
8
|
+
bdB6PFmKr0FYXZX67KwFyN/s/IXEpaCfJIEjPF7VJDXW+p4XMGkPuIgGki7+8u9p
|
|
9
|
+
ZfhP5rZPPxEyWxjruS72nxfPC97G7LhSh40i5KGAQIYaSYuPuhUr+3xEdF8DVmA1
|
|
10
|
+
x+JtXBkIBfrIfC64qDwVk1QTUn0FhYsBBL8L4eynED/pRaToOWPggZSmie1nYAtE
|
|
11
|
+
pzNgAACOIO13AgMBAAGjbzBtMCsGA1UdEQQkMCKCDXRhbmdvaG9zdC5jb22CEXd3
|
|
12
|
+
dy50YW5nb2hvc3QuY29tMB0GA1UdDgQWBBS7FibNCjP8A4HR4SrlP5taWQfPmjAf
|
|
13
|
+
BgNVHSMEGDAWgBSSJvQM9T2E+PfGJjmEeMdyCr9s1zANBgkqhkiG9w0BAQsFAAOC
|
|
14
|
+
AQEAQPTJ95Lu7RhObp8ONTfbt275GsO7osRqPX8EoWsySu1Vhs7BWvOgs0zlRgo2
|
|
15
|
+
QSAyXuW5ZmHEVvq1OOfsA/HAkZn0H1h6z6Fz7RHlgYLFhkd6IAE8JIg705a9w2Zo
|
|
16
|
+
denA9PV2SFCsEEIa7hQ/BG4YgvBvf7pCOtdHg3WlUyhLMvkENJh2m/x4AATmICqs
|
|
17
|
+
uNCu0HuxpaitaiqtTyXcAy1yRITPoZYfKt66j6MmEaPB/e0Rs3GcQuY2VsTb3YYS
|
|
18
|
+
q5cEjxxOhDZL50d2F4UTwoy9244lBgIO/T1MCMlnLuqMmRDxvF4drTmt2QjShJ6n
|
|
19
|
+
z/x7eUUMGyBbHqBE73ZgG26eEQ==
|
|
20
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDXAn3dqIFuMjAp
|
|
3
|
+
Qp1HL+V3O6rTxgH5Z+0x3PqFegGDD1sPR1FNj9X5WfG7cipZgvQsjVI8xE/b8j9B
|
|
4
|
+
DLyUdhyIiDiDGnz4goGE45t6n3kN9llaOLHEvPliZSx/XuCseu6LbzwMGJc6bdB6
|
|
5
|
+
PFmKr0FYXZX67KwFyN/s/IXEpaCfJIEjPF7VJDXW+p4XMGkPuIgGki7+8u9pZfhP
|
|
6
|
+
5rZPPxEyWxjruS72nxfPC97G7LhSh40i5KGAQIYaSYuPuhUr+3xEdF8DVmA1x+Jt
|
|
7
|
+
XBkIBfrIfC64qDwVk1QTUn0FhYsBBL8L4eynED/pRaToOWPggZSmie1nYAtEpzNg
|
|
8
|
+
AACOIO13AgMBAAECggEADjLz7Pd71LMryw3DJThchwtBtMqWxsm+OFTHlpkAEI+r
|
|
9
|
+
C89B50VgdB8kf6SCd3bWeTq7+5dbTsMoujsFGSjTqZCVatMM/bxgoU4GroppjCqA
|
|
10
|
+
rByiYMO6FG1qCt9RJxLXPg4SgRn+orUt12S05Ru9zQAhL3kBw0AIybXDf8EQYnH/
|
|
11
|
+
tbRhx3/YHcaIgRjzd/zTBmfgmiYNGInNO8q2O6UssuHpdFC2YPHkdHhLZNWX5gBz
|
|
12
|
+
0VHK++ff4ZkpzOOZVlS//UoKMMtwez4dutu+ZX7jGCeXkKEwuNyXmPBRj5vpeGoy
|
|
13
|
+
J/CaGArR+7ut/dOqZv7bEF5bp6dZWXxjdHtaga+OwQKBgQDw2efq+In79MfRgdJt
|
|
14
|
+
duk0wkuGress648qzPczGfLu7LzwY7Q+QUVPgrziUmkEgw/Xvw+TarLi1KaBizYt
|
|
15
|
+
yP2kB3HP7Z4Xufe7M3N/98S9VcOELH8/MT4L5uxhkqeaJ0n4ev3alEih4HKCL4Bs
|
|
16
|
+
NKqdWPds6EE+hOoVsTJLS17JowKBgQDkiH8SJ0WL4zmGknEdI3CB7BbsVlCtR/Wx
|
|
17
|
+
Qw6fsn5Fwian7SfMLJSc3FpZ2E0BM8PJKNLoXU9sxGRgQT0HczGFyAKW9ifh4K/r
|
|
18
|
+
EovG4+9Xh9s56c8AFTs6mMQgL1lhsFgyzUwNxscGOTqp949QAHe7QLY6G5IzYi3q
|
|
19
|
+
/8p0m5jyHQKBgDrYQn16M9xHNfrOCSeNgfTN8734CBl1hAklAtCNanlNhewFsCf1
|
|
20
|
+
soV2n8d78wSTMO+5Uojl7MbWxceox5fwH2hQGVJ/77xER26JZ5LAamUH6zkD1iMO
|
|
21
|
+
WOZ3iRFdz20uZDg9dIBO8l/6gn+kM3A8feLrtaf6JtarirW6EVusEoCZAoGAOoRM
|
|
22
|
+
7UwK/ce/+hpTRl/Fti7Kq9dqLwSG/82o1/FvbdNJ7KPIFfqwTv4JUIoXJaComECQ
|
|
23
|
+
yJjj9njPLuplgxvW6WeOajM7gRX0VZ/ZFKNWrLYHx2t76oyFLvrg9VDKdT4fR1rU
|
|
24
|
+
B48HdSuAPvc5xgVooxTt1DEtHWUdVtgKchNJdW0CgYBdYIBZr/tafno7kXJAGl2Q
|
|
25
|
+
/I7hNXvtAsw8OMU8mls6DXc2RXxO1J4V67IjBoyqyFoBZD10N5Si7vxgCdIv9Vhc
|
|
26
|
+
b/wQAHC9b2C4qX2i6UlUL60XQmNlGchh/fLL8R9dOE0+rhvkkK+CyF2vRUuGxchE
|
|
27
|
+
JZdQ89koDLYQMtdzeEGnOg==
|
|
28
|
+
-----END PRIVATE KEY-----
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# The off-fleet host's own vhost. celilo does NOT manage this file — the point
|
|
2
|
+
# of external_web is that the host owns its web server, TLS, and DNS, and
|
|
3
|
+
# celilo only drops files into the document root.
|
|
4
|
+
<VirtualHost *:80>
|
|
5
|
+
ServerName tangohost.com
|
|
6
|
+
ServerAlias www.tangohost.com
|
|
7
|
+
DocumentRoot /home/theglo18/tangohost.com
|
|
8
|
+
<Directory /home/theglo18/tangohost.com>
|
|
9
|
+
Options -Indexes +FollowSymLinks
|
|
10
|
+
AllowOverride All
|
|
11
|
+
Require all granted
|
|
12
|
+
</Directory>
|
|
13
|
+
</VirtualHost>
|
|
14
|
+
|
|
15
|
+
<VirtualHost *:443>
|
|
16
|
+
ServerName tangohost.com
|
|
17
|
+
ServerAlias www.tangohost.com
|
|
18
|
+
DocumentRoot /home/theglo18/tangohost.com
|
|
19
|
+
SSLEngine on
|
|
20
|
+
SSLCertificateFile /etc/ssl/cpanel-sim/site-tls.crt
|
|
21
|
+
SSLCertificateKeyFile /etc/ssl/cpanel-sim/site-tls.key
|
|
22
|
+
<Directory /home/theglo18/tangohost.com>
|
|
23
|
+
Options -Indexes +FollowSymLinks
|
|
24
|
+
AllowOverride All
|
|
25
|
+
Require all granted
|
|
26
|
+
</Directory>
|
|
27
|
+
</VirtualHost>
|
package/config/dns/com.zone
CHANGED
|
@@ -9,3 +9,10 @@ com. IN NS tld-dns.lab.
|
|
|
9
9
|
|
|
10
10
|
park-your-domain IN NS ns1.park-your-domain.com.
|
|
11
11
|
ns1.park-your-domain.com. IN A 100.64.0.55
|
|
12
|
+
|
|
13
|
+
; The OFF-FLEET web host (external_web). Unlike every customer name, this one
|
|
14
|
+
; resolves to the host's OWN public address (100.64.0.63), NOT the customer
|
|
15
|
+
; firewall — because the host genuinely is a third party out on the internet,
|
|
16
|
+
; not a service behind the customer's NAT. No RFC1918 leak: .62 is public.
|
|
17
|
+
tangohost IN NS ns1.tangohost.com.
|
|
18
|
+
ns1.tangohost.com. IN A 100.64.0.55
|
|
@@ -14,6 +14,12 @@ zone:
|
|
|
14
14
|
file: "/config/example.net.zone"
|
|
15
15
|
storage: "/var/lib/knot"
|
|
16
16
|
|
|
17
|
+
# The OFF-FLEET web host's own zone. Served here only because this is the
|
|
18
|
+
# simulator's authoritative nameserver; celilo never writes to it.
|
|
19
|
+
- domain: "tangohost.com"
|
|
20
|
+
file: "/config/tangohost.com.zone"
|
|
21
|
+
storage: "/var/lib/knot"
|
|
22
|
+
|
|
17
23
|
- domain: "park-your-domain.com"
|
|
18
24
|
file: "/config/park-your-domain.com.zone"
|
|
19
25
|
storage: "/var/lib/knot"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
$ORIGIN tangohost.com.
|
|
2
|
+
$TTL 300
|
|
3
|
+
|
|
4
|
+
@ IN SOA ns1.tangohost.com. admin.tangohost.com. (
|
|
5
|
+
2026072901 300 60 604800 300
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
; The OFF-FLEET host's own public DNS — it owns this zone, celilo does not.
|
|
9
|
+
; Both names point at the host's own public address, NOT the customer
|
|
10
|
+
; firewall (100.100.0.100): this host lives out on the simulated internet.
|
|
11
|
+
@ IN NS ns1.tangohost.com.
|
|
12
|
+
ns1 IN A 100.64.0.55
|
|
13
|
+
@ IN A 100.64.0.63
|
|
14
|
+
www IN A 100.64.0.63
|
|
@@ -23,6 +23,21 @@ server:
|
|
|
23
23
|
local-data: "npm-registry.lab. IN A 100.64.0.59"
|
|
24
24
|
# MinIO S3 simulator — backup/restore target. See SIMULATOR_IPS.MINIO.
|
|
25
25
|
local-data: "minio.lab. IN A 100.64.0.61"
|
|
26
|
+
# apt-repo simulator. Also needed HERE, not only in the internal resolver:
|
|
27
|
+
# module target hosts resolve through the PUBLIC resolver, and in production
|
|
28
|
+
# apt.celilo.computer is a publicly-resolvable name — so a host fetching a
|
|
29
|
+
# package from it is the faithful case, not a shortcut.
|
|
30
|
+
local-data: "apt.celilo.lab. IN A 100.64.0.60"
|
|
31
|
+
# signal-cli daemon (real, unlinked) and its simulator counterpart. Both
|
|
32
|
+
# sit on the `internal` network — celilo-mgr reaches a notification
|
|
33
|
+
# transport locally; a transport needing public ingress could not tell
|
|
34
|
+
# you the ingress was broken.
|
|
35
|
+
local-data: "signal-cli.lab. IN A 192.168.0.90"
|
|
36
|
+
local-data: "signal-sim.lab. IN A 192.168.0.91"
|
|
37
|
+
# signal-cli release host — the sim internet's stand-in for GitHub
|
|
38
|
+
# releases, so the signal module's deploy-time download resolves inside
|
|
39
|
+
# the sealed network. See SIMULATOR_IPS.SIGNAL_RELEASE.
|
|
40
|
+
local-data: "signal-release.lab. IN A 100.64.0.62"
|
|
26
41
|
# External website prober simulator — without this override, isitup.org
|
|
27
42
|
# falls through the "forward-zone: ." below and resolves to the REAL
|
|
28
43
|
# Namecheap-parked domain on the public internet.
|
|
@@ -50,6 +65,17 @@ stub-zone:
|
|
|
50
65
|
name: "park-your-domain.com."
|
|
51
66
|
stub-addr: 100.64.0.55
|
|
52
67
|
|
|
68
|
+
# The OFF-FLEET web host's domain (external_web). Like every other simulated
|
|
69
|
+
# domain it needs a stub, or it falls through to the real internet — and
|
|
70
|
+
# tangohost.com is a REAL registered name out there, so the leak resolves to a
|
|
71
|
+
# real address and the SSH bootstrap times out against a stranger's server.
|
|
72
|
+
# namecheap-dns is authoritative for the zone; the zone points at the host's own
|
|
73
|
+
# public address (100.64.0.63), NOT the customer firewall, because the host
|
|
74
|
+
# genuinely is a third party on the internet.
|
|
75
|
+
stub-zone:
|
|
76
|
+
name: "tangohost.com."
|
|
77
|
+
stub-addr: 100.64.0.55
|
|
78
|
+
|
|
53
79
|
# Everything else → the real internet, via Docker's embedded resolver.
|
|
54
80
|
#
|
|
55
81
|
# 127.0.0.11 is Docker's per-container DNS; it relays to whatever the HOST is
|
|
@@ -13,7 +13,22 @@ ip route add 10.0.30.0/24 via 100.100.0.100 # secure via fw-isp
|
|
|
13
13
|
|
|
14
14
|
# IP forwarding is set via sysctls in docker-compose
|
|
15
15
|
|
|
16
|
-
# NAT/forward between isp-external and internet-external
|
|
16
|
+
# NAT/forward between isp-external and internet-external.
|
|
17
|
+
#
|
|
18
|
+
# The customer's public /24 is ROUTED, never re-NAT'd. An ISP does not NAT a
|
|
19
|
+
# subscriber that already holds a public address — the whole point of
|
|
20
|
+
# 100.100.0.100 is that it IS the customer's address on the internet. fw-ext
|
|
21
|
+
# used to MASQUERADE it anyway, so every packet leaving the fleet reached the
|
|
22
|
+
# public simulators bearing fw-ext's own 100.64.0.1.
|
|
23
|
+
#
|
|
24
|
+
# That is not cosmetic. Namecheap-style DDNS registers the SOURCE address of
|
|
25
|
+
# the update when the caller omits `ip=` (which is now how celilo registers
|
|
26
|
+
# public names — #464/#466), so the double NAT published 100.64.0.1 for every
|
|
27
|
+
# public hostname: an address that DNATs to nothing, breaking ACME validation
|
|
28
|
+
# and any inbound reach. It also silently clobbered seeded apex records.
|
|
29
|
+
# Anything that reasons about "the address the internet sees us as" was
|
|
30
|
+
# measuring the simulator's own artefact.
|
|
31
|
+
iptables -t nat -A POSTROUTING -s 100.100.0.0/24 -j RETURN
|
|
17
32
|
iptables -t nat -A POSTROUTING -j MASQUERADE
|
|
18
33
|
iptables -P FORWARD ACCEPT
|
|
19
34
|
|
|
@@ -22,17 +22,27 @@ chmod 600 /root/.ssh/config
|
|
|
22
22
|
# Routing — DEFAULT_GATEWAY comes from docker-compose environment
|
|
23
23
|
# default: 192.168.0.1 (fw-isp), direct-internet: 192.168.0.254 (fw-main)
|
|
24
24
|
GATEWAY="${DEFAULT_GATEWAY:-192.168.0.1}"
|
|
25
|
+
# Next hop into the segmented zones. On the default topology celilo-mgr is on the
|
|
26
|
+
# internal LAN and reaches them via fw-main's internal leg (192.168.0.254). When
|
|
27
|
+
# celilo-mgr lives on its OWN control-plane network (managementZone secure-mgmt),
|
|
28
|
+
# it reaches them via fw-main's leg on THAT network instead.
|
|
29
|
+
FW_MAIN="${FW_MAIN_HOP:-192.168.0.254}"
|
|
25
30
|
ip route del default 2>/dev/null || true
|
|
26
31
|
ip route add default via "$GATEWAY"
|
|
27
|
-
ip route add 10.0.10.0/24 via
|
|
28
|
-
ip route add 10.0.20.0/24 via
|
|
29
|
-
ip route add 10.0.30.0/24 via
|
|
32
|
+
ip route add 10.0.10.0/24 via "$FW_MAIN" # dmz via fw-main
|
|
33
|
+
ip route add 10.0.20.0/24 via "$FW_MAIN" # app via fw-main
|
|
34
|
+
ip route add 10.0.30.0/24 via "$FW_MAIN" # secure via fw-main
|
|
35
|
+
# Control plane. Only reachable when a secure-mgmt network exists — that is,
|
|
36
|
+
# when celilo-mgr lives there itself, or when a module declaring
|
|
37
|
+
# `zone: secure-mgmt` needs a system to land on (#436). Tolerated silently
|
|
38
|
+
# otherwise so the default topology is unchanged.
|
|
39
|
+
ip route add 10.0.120.0/24 via "$FW_MAIN" 2>/dev/null || true
|
|
30
40
|
|
|
31
41
|
# DNS — Technitium internal resolver (split-horizon) with public fallback.
|
|
32
42
|
# Technitium at 192.168.0.10 is authoritative for iamtheinternet.org internally,
|
|
33
43
|
# resolving www/auth to Caddy's DMZ IP (10.0.10.10) rather than the public WAN IP.
|
|
34
44
|
# Fall back to the simulated public resolver if Technitium is not yet up.
|
|
35
|
-
printf 'nameserver
|
|
45
|
+
printf 'nameserver %s\nnameserver 100.100.0.1\n' "${INTERNAL_RESOLVER:-192.168.0.10}" > /etc/resolv.conf
|
|
36
46
|
|
|
37
47
|
# Fetch Pebble's runtime ACME root CA (Pebble generates a fresh root at each
|
|
38
48
|
# startup, unlike the static /config/pebble/pebble-ca.crt baked in at build
|
|
@@ -7,6 +7,15 @@
|
|
|
7
7
|
# `mc mb --ignore-existing`.
|
|
8
8
|
set -e
|
|
9
9
|
|
|
10
|
+
# Route the customer's public prefix via the ISP edge (fw-ext), like every
|
|
11
|
+
# other host on internet-external. Docker's default bridge gateway has no path
|
|
12
|
+
# across networks, so without this a reply to the customer's WAN address is
|
|
13
|
+
# dropped and `backup --storage` hangs. fw-ext is per-test, so this is
|
|
14
|
+
# expected to fail while shared infra runs alone — hence the tolerance.
|
|
15
|
+
# (`busybox ip` because the MinIO image ships no iproute2.)
|
|
16
|
+
busybox ip route del default 2>/dev/null || true
|
|
17
|
+
busybox ip route add default via 100.64.0.1 2>/dev/null || true
|
|
18
|
+
|
|
10
19
|
# Serve the S3 API on :80 so the management box reaches it over the SAME
|
|
11
20
|
# proven HTTP egress path as the other public sims (apt-repo, npm-registry):
|
|
12
21
|
# fw-ext's Squid-bypass exception is scoped to dport 80/443 → 100.64.0.0/24, so
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Entrypoint wrapper for a simulator on `internet-external` — a host out on
|
|
3
|
+
# the simulated public internet.
|
|
4
|
+
#
|
|
5
|
+
# Such a host must reach the customer's public prefix (100.100.0.0/24) through
|
|
6
|
+
# the ISP edge, fw-ext. Docker's default bridge gateway has no path across
|
|
7
|
+
# networks, so without this route a reply to the customer's WAN address is
|
|
8
|
+
# simply dropped and the connection hangs.
|
|
9
|
+
#
|
|
10
|
+
# This used to be invisible: fw-ext MASQUERADEd the customer to its own
|
|
11
|
+
# 100.64.0.1, which is on-link here, so replies never needed routing at all.
|
|
12
|
+
# Once fw-ext stopped re-NATing a subscriber that already holds a public
|
|
13
|
+
# address (the ISP routes it; it does not NAT it), the omission surfaced —
|
|
14
|
+
# every sim that had this route already kept working, and the four that did
|
|
15
|
+
# not started timing out. celilo-website-sim, isitup, pebble, namecheap-dns
|
|
16
|
+
# and the DNS hierarchy have carried it all along; this is the same two lines.
|
|
17
|
+
#
|
|
18
|
+
# fw-ext is per-test, so the route is unreachable while shared infra runs
|
|
19
|
+
# alone. That is harmless — nothing dials the customer before a test brings
|
|
20
|
+
# fw-ext up — hence the tolerant `|| true`.
|
|
21
|
+
ip route del default 2>/dev/null || true
|
|
22
|
+
ip route add default via 100.64.0.1 2>/dev/null || true
|
|
23
|
+
|
|
24
|
+
exec "$@"
|
|
@@ -57,6 +57,16 @@ $(printf "${SPLIT_HORIZON_BLOCK}")
|
|
|
57
57
|
# MinIO S3 simulator — backup/restore target for the migration e2e.
|
|
58
58
|
# See SIMULATOR_IPS.MINIO.
|
|
59
59
|
local-data: "minio.lab. IN A 100.64.0.61"
|
|
60
|
+
# signal-cli daemon (real, unlinked) and its simulator counterpart. Both
|
|
61
|
+
# sit on the `internal` network — celilo-mgr reaches a notification
|
|
62
|
+
# transport locally; a transport needing public ingress could not tell
|
|
63
|
+
# you the ingress was broken.
|
|
64
|
+
local-data: "signal-cli.lab. IN A 192.168.0.90"
|
|
65
|
+
local-data: "signal-sim.lab. IN A 192.168.0.91"
|
|
66
|
+
# signal-cli release host — the sim internet's stand-in for GitHub
|
|
67
|
+
# releases, so the signal module's deploy-time download resolves inside
|
|
68
|
+
# the sealed network. See SIMULATOR_IPS.SIGNAL_RELEASE.
|
|
69
|
+
local-data: "signal-release.lab. IN A 100.64.0.62"
|
|
60
70
|
|
|
61
71
|
forward-zone:
|
|
62
72
|
name: "."
|
|
@@ -49,8 +49,16 @@ RUN set -eux; \
|
|
|
49
49
|
-o APT::FTPArchive::Release::Architectures="amd64 arm64" \
|
|
50
50
|
release dists/stable > dists/stable/Release
|
|
51
51
|
|
|
52
|
+
# Route the customer's public prefix via the ISP edge, like every other host
|
|
53
|
+
# on internet-external. See config/routing/public-sim-entrypoint.sh.
|
|
54
|
+
RUN apt-get update \
|
|
55
|
+
&& apt-get install -y --no-install-recommends iproute2 \
|
|
56
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
57
|
+
COPY config/routing/public-sim-entrypoint.sh /usr/local/bin/public-sim-entrypoint.sh
|
|
58
|
+
|
|
52
59
|
EXPOSE 80
|
|
53
60
|
|
|
54
61
|
# python3's http.server is enough for apt (GET + range requests over static
|
|
55
62
|
# files). No special MIME/headers needed.
|
|
63
|
+
ENTRYPOINT ["/bin/sh", "/usr/local/bin/public-sim-entrypoint.sh"]
|
|
56
64
|
CMD ["python3", "-m", "http.server", "80", "--directory", "/repo"]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# An OFF-FLEET web host: a third-party cPanel/SSH shared account that celilo
|
|
2
|
+
# publishes to but does NOT govern. It is a PUBLIC PEER on `internet-external`
|
|
3
|
+
# alongside namecheap-dns and pebble — NOT behind the customer firewall — so
|
|
4
|
+
# public DNS resolving its domain to its own address bends no RFC1918 rule.
|
|
5
|
+
#
|
|
6
|
+
# Faithful to what we verified against the live A2/CloudLinux account:
|
|
7
|
+
# - sshd on 7822, an unprivileged account (no root, no systemd control)
|
|
8
|
+
# - Apache + mod_rewrite serving the stock WordPress .htaccess, so a real
|
|
9
|
+
# directory under the docroot is served BEFORE the CMS front controller
|
|
10
|
+
# - the domain's TLS certificate pre-installed (as AutoSSL would leave it),
|
|
11
|
+
# not obtained via ACME — external_web never owns TLS
|
|
12
|
+
# - ~/.cpanel/userdata/<domain> carrying the authoritative documentroot
|
|
13
|
+
#
|
|
14
|
+
# No systemd: sshd + apache are all this host runs, so a two-process entrypoint
|
|
15
|
+
# is enough and boots in a fraction of the time.
|
|
16
|
+
FROM ubuntu:22.04
|
|
17
|
+
|
|
18
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
19
|
+
|
|
20
|
+
COPY config/apt/99retries.conf /etc/apt/apt.conf.d/99retries.conf
|
|
21
|
+
|
|
22
|
+
RUN apt-get update && apt-get install -y \
|
|
23
|
+
openssh-server \
|
|
24
|
+
apache2 \
|
|
25
|
+
ca-certificates \
|
|
26
|
+
iproute2 \
|
|
27
|
+
iputils-ping \
|
|
28
|
+
curl \
|
|
29
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
30
|
+
|
|
31
|
+
RUN a2enmod rewrite ssl && a2dissite 000-default
|
|
32
|
+
|
|
33
|
+
# sshd on 7822 with password auth ON — the bootstrap's whole job is to log in
|
|
34
|
+
# with the account password once and install celilo's key, so the account must
|
|
35
|
+
# accept a password until that happens (as a real shared host does).
|
|
36
|
+
RUN mkdir -p /run/sshd && \
|
|
37
|
+
sed -i 's/^#\?Port .*/Port 7822/' /etc/ssh/sshd_config && \
|
|
38
|
+
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
|
|
39
|
+
sed -i 's/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config && \
|
|
40
|
+
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
|
|
41
|
+
|
|
42
|
+
# The account. Unprivileged and NOT in sudo — celilo cannot run a daemon, bind
|
|
43
|
+
# a port, or touch the firewall here. That inability is what "off-fleet" means.
|
|
44
|
+
RUN useradd -m -s /bin/bash theglo18 && \
|
|
45
|
+
echo 'theglo18:tango-e2e-password' | chpasswd
|
|
46
|
+
|
|
47
|
+
# The host's own site, in the account's home the way cPanel lays an addon
|
|
48
|
+
# domain out, plus the userdata file external_web reads the docroot from.
|
|
49
|
+
COPY config/cpanel-host/docroot/ /home/theglo18/tangohost.com/
|
|
50
|
+
RUN mkdir -p /home/theglo18/.cpanel/userdata && \
|
|
51
|
+
printf 'documentroot: /home/theglo18/tangohost.com\nservername: tangohost.com\nuser: theglo18\n' \
|
|
52
|
+
> /home/theglo18/.cpanel/userdata/tangohost.com && \
|
|
53
|
+
chown -R theglo18:theglo18 /home/theglo18
|
|
54
|
+
|
|
55
|
+
# Apache runs as www-data but must read/serve files the account writes.
|
|
56
|
+
RUN usermod -aG theglo18 www-data && chmod 755 /home/theglo18
|
|
57
|
+
|
|
58
|
+
# Pre-installed TLS for the domain (a committed sim CA + leaf, so the cert is
|
|
59
|
+
# deterministic). mgmt trusts this CA — see Dockerfile.management.
|
|
60
|
+
COPY config/cpanel-host/site-tls.crt config/cpanel-host/site-tls.key /etc/ssl/cpanel-sim/
|
|
61
|
+
COPY config/cpanel-host/site.conf /etc/apache2/sites-available/tangohost.conf
|
|
62
|
+
RUN a2ensite tangohost && chmod 600 /etc/ssl/cpanel-sim/site-tls.key
|
|
63
|
+
|
|
64
|
+
EXPOSE 7822 80 443
|
|
65
|
+
|
|
66
|
+
# apache2 is PID 1; sshd runs beside it. If either dies the container exits,
|
|
67
|
+
# which is what we want from a fixture host. The runtime/lock dirs live under
|
|
68
|
+
# /var/run, which the container wipes at start, so recreate them before apache
|
|
69
|
+
# reads DefaultRuntimeDir.
|
|
70
|
+
# Route the customer's public prefix via the ISP edge, like every other host
|
|
71
|
+
# on internet-external. See config/routing/public-sim-entrypoint.sh.
|
|
72
|
+
COPY config/routing/public-sim-entrypoint.sh /usr/local/bin/public-sim-entrypoint.sh
|
|
73
|
+
|
|
74
|
+
ENTRYPOINT ["/bin/sh", "/usr/local/bin/public-sim-entrypoint.sh"]
|
|
75
|
+
CMD ["/bin/sh", "-c", "mkdir -p /var/run/apache2 /var/lock/apache2 /run/sshd && /usr/sbin/sshd && . /etc/apache2/envvars && exec apache2 -D FOREGROUND"]
|
|
@@ -12,8 +12,20 @@ RUN apt-get update && apt-get install -y \
|
|
|
12
12
|
dnsutils \
|
|
13
13
|
procps \
|
|
14
14
|
python3 \
|
|
15
|
+
wireguard-tools \
|
|
16
|
+
wireguard-go \
|
|
15
17
|
&& rm -rf /var/lib/apt/lists/*
|
|
16
18
|
|
|
19
|
+
# Containers have no wireguard kernel module to load, and a test must not depend
|
|
20
|
+
# on whether the Docker host happens to have one. wg-quick falls back to this
|
|
21
|
+
# userspace implementation when `ip link add type wireguard` fails, so the tunnel
|
|
22
|
+
# behaves the same on any host — it just needs /dev/net/tun + NET_ADMIN.
|
|
23
|
+
# NOTE the value: Ubuntu's `wireguard-go` package installs its binary as
|
|
24
|
+
# /usr/bin/wireguard, NOT `wireguard-go`. Naming the binary wrong here fails
|
|
25
|
+
# only on a host WITHOUT the kernel module — i.e. it passes locally and
|
|
26
|
+
# breaks in CI, which is the worst possible way for this to be wrong.
|
|
27
|
+
ENV WG_QUICK_USERSPACE_IMPLEMENTATION=wireguard
|
|
28
|
+
|
|
17
29
|
RUN mkdir -p /run/sshd && \
|
|
18
30
|
sed -i 's/#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config && \
|
|
19
31
|
sed -i 's/#PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
|
@@ -44,6 +44,12 @@ RUN chsh -s /bin/zsh root
|
|
|
44
44
|
COPY config/proxy/squid-ca.crt /usr/local/share/ca-certificates/e2e-proxy-ca.crt
|
|
45
45
|
# Trust Pebble's test CA (so bun fetch() trusts certs issued by the simulated Let's Encrypt)
|
|
46
46
|
COPY config/pebble/pebble-ca.crt /usr/local/share/ca-certificates/pebble-ca.crt
|
|
47
|
+
# Trust the OFF-FLEET cPanel host sim's CA. That host's cert is PRE-INSTALLED
|
|
48
|
+
# (as a real shared host's AutoSSL cert is) rather than issued by Pebble —
|
|
49
|
+
# external_web never owns TLS — so its CA is a separate, static trust anchor.
|
|
50
|
+
# external_web's authoritative post-publish check HTTPS-GETs the route from
|
|
51
|
+
# here, which is why mgmt in particular must trust it.
|
|
52
|
+
COPY config/cpanel-host/cpanel-host-ca.crt /usr/local/share/ca-certificates/cpanel-host-ca.crt
|
|
47
53
|
RUN update-ca-certificates
|
|
48
54
|
|
|
49
55
|
# Tell bun (and Node-compat code) to merge the system CA bundle with
|
package/docker/Dockerfile.minio
CHANGED
|
@@ -19,8 +19,15 @@
|
|
|
19
19
|
|
|
20
20
|
FROM minio/mc:latest AS mc
|
|
21
21
|
|
|
22
|
+
# Static busybox purely for its `ip` applet: the MinIO image has no iproute2
|
|
23
|
+
# and no package manager worth invoking, but it still needs the ISP route
|
|
24
|
+
# every host on internet-external carries (see minio-startup.sh).
|
|
25
|
+
FROM busybox:stable-musl AS busybox
|
|
26
|
+
|
|
22
27
|
FROM minio/minio:latest
|
|
23
28
|
|
|
29
|
+
COPY --from=busybox /bin/busybox /usr/local/bin/busybox
|
|
30
|
+
|
|
24
31
|
# Bring the MinIO client in from the mc image so the entrypoint can create the
|
|
25
32
|
# bucket once the server is up.
|
|
26
33
|
COPY --from=mc /usr/bin/mc /usr/bin/mc
|
|
@@ -22,5 +22,13 @@ ENV PACKUMENT_DIR=/var/lib/npm \
|
|
|
22
22
|
PORT=80 \
|
|
23
23
|
REGISTRY_URL=http://npm-registry.lab
|
|
24
24
|
|
|
25
|
+
# Route the customer's public prefix via the ISP edge, like every other host
|
|
26
|
+
# on internet-external. See config/routing/public-sim-entrypoint.sh.
|
|
27
|
+
RUN apt-get update \
|
|
28
|
+
&& apt-get install -y --no-install-recommends iproute2 \
|
|
29
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
30
|
+
COPY config/routing/public-sim-entrypoint.sh /usr/local/bin/public-sim-entrypoint.sh
|
|
31
|
+
|
|
25
32
|
EXPOSE 80
|
|
33
|
+
ENTRYPOINT ["/bin/sh", "/usr/local/bin/public-sim-entrypoint.sh"]
|
|
26
34
|
CMD ["bun", "run", "src/server.ts"]
|
|
@@ -18,8 +18,19 @@ RUN apt-get update && apt-get install -y \
|
|
|
18
18
|
iputils-ping \
|
|
19
19
|
iproute2 \
|
|
20
20
|
ca-certificates \
|
|
21
|
+
wireguard-tools \
|
|
22
|
+
wireguard-go \
|
|
21
23
|
&& rm -rf /var/lib/apt/lists/*
|
|
22
24
|
|
|
25
|
+
# A vantage may need to dial a VPN and probe from INSIDE the tunnel — the only
|
|
26
|
+
# way to assert VPN reach by real signal rather than by reading a rule string.
|
|
27
|
+
# Userspace implementation so the test doesn't depend on the Docker host's kernel.
|
|
28
|
+
# NOTE the value: Ubuntu's `wireguard-go` package installs its binary as
|
|
29
|
+
# /usr/bin/wireguard, NOT `wireguard-go`. Naming the binary wrong here fails
|
|
30
|
+
# only on a host WITHOUT the kernel module — i.e. it passes locally and
|
|
31
|
+
# breaks in CI, which is the worst possible way for this to be wrong.
|
|
32
|
+
ENV WG_QUICK_USERSPACE_IMPLEMENTATION=wireguard
|
|
33
|
+
|
|
23
34
|
COPY config/routing/observer-setup.sh /startup.sh
|
|
24
35
|
RUN chmod +x /startup.sh
|
|
25
36
|
|
|
@@ -30,5 +30,13 @@ ENV DATA_DIR=/var/lib/celilo-registry \
|
|
|
30
30
|
# somewhere to put files before the server runs.
|
|
31
31
|
RUN mkdir -p /uploads
|
|
32
32
|
|
|
33
|
+
# Route the customer's public prefix via the ISP edge, like every other host
|
|
34
|
+
# on internet-external. See config/routing/public-sim-entrypoint.sh.
|
|
35
|
+
RUN apt-get update \
|
|
36
|
+
&& apt-get install -y --no-install-recommends iproute2 \
|
|
37
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
38
|
+
COPY config/routing/public-sim-entrypoint.sh /usr/local/bin/public-sim-entrypoint.sh
|
|
39
|
+
|
|
33
40
|
EXPOSE 80
|
|
41
|
+
ENTRYPOINT ["/bin/sh", "/usr/local/bin/public-sim-entrypoint.sh"]
|
|
34
42
|
CMD ["bun", "run", "src/index.ts"]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Real signal-cli, for verifying celilo's client against the actual JSON-RPC
|
|
2
|
+
# interface rather than against a simulator that encodes our assumptions.
|
|
3
|
+
#
|
|
4
|
+
# The account is never linked. That is deliberate and sufficient: signal-cli's
|
|
5
|
+
# HTTP interface is served locally and does not touch Signal's network, so the
|
|
6
|
+
# endpoint paths, envelope shapes, error shapes, SSE receive stream, and the
|
|
7
|
+
# Host/Content-Type guards are all verifiable without an account.
|
|
8
|
+
#
|
|
9
|
+
# What an unlinked daemon CANNOT verify is that a linked account delivers a
|
|
10
|
+
# message to a phone. That needs Signal's real network. DNS is ours in e2e and
|
|
11
|
+
# even the TLS trust store is a swappable classpath resource (`whisper.store`,
|
|
12
|
+
# password "whisper" — see StagingConfig.java), but CDSI/SVR2 use SGX remote
|
|
13
|
+
# attestation whose whole purpose is to make substitution impossible. That
|
|
14
|
+
# limit is real; everything short of it is not.
|
|
15
|
+
#
|
|
16
|
+
# Three facts learned by RUNNING this rather than reading about it:
|
|
17
|
+
# - signal-cli 0.14.6 ships class-file version 69, so it needs a Java 25 JRE.
|
|
18
|
+
# A 21 base dies at startup with UnsupportedClassVersionError.
|
|
19
|
+
# - it needs the native libsignal-client (signal_jni), shipped x86_64 only —
|
|
20
|
+
# as is the "Linux-native" build. Hence the amd64 pin.
|
|
21
|
+
# - extracting the tarball inside the amd64 stage fails under qemu on an
|
|
22
|
+
# arm64 host ("Cannot mkdir: Function not implemented"), so the fetch runs
|
|
23
|
+
# on the builder's own architecture and only the files cross over.
|
|
24
|
+
|
|
25
|
+
ARG SIGNAL_CLI_VERSION=0.14.6
|
|
26
|
+
|
|
27
|
+
FROM --platform=$BUILDPLATFORM debian:bookworm-slim AS fetch
|
|
28
|
+
ARG SIGNAL_CLI_VERSION
|
|
29
|
+
RUN apt-get update \
|
|
30
|
+
&& apt-get install -y --no-install-recommends curl ca-certificates \
|
|
31
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
32
|
+
# Fetched at BUILD time — the e2e network is sealed at run time.
|
|
33
|
+
RUN curl -fsSL \
|
|
34
|
+
"https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}.tar.gz" \
|
|
35
|
+
-o /tmp/signal-cli.tar.gz \
|
|
36
|
+
&& mkdir -p /out \
|
|
37
|
+
&& tar -xzf /tmp/signal-cli.tar.gz -C /out \
|
|
38
|
+
&& mv "/out/signal-cli-${SIGNAL_CLI_VERSION}" /out/signal-cli
|
|
39
|
+
# The published JSON schemas are the authoritative description of the JSON-RPC
|
|
40
|
+
# surface — a test can assert against them rather than against prose.
|
|
41
|
+
RUN curl -fsSL \
|
|
42
|
+
"https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-json-schemas.tar.gz" \
|
|
43
|
+
-o /tmp/schemas.tar.gz \
|
|
44
|
+
&& mkdir -p /out/schemas \
|
|
45
|
+
&& tar -xzf /tmp/schemas.tar.gz -C /out/schemas
|
|
46
|
+
|
|
47
|
+
FROM --platform=linux/amd64 eclipse-temurin:25-jre
|
|
48
|
+
COPY --from=fetch /out/signal-cli /opt/signal-cli
|
|
49
|
+
COPY --from=fetch /out/schemas /opt/signal-cli-schemas
|
|
50
|
+
|
|
51
|
+
ENV PATH="/opt/signal-cli/bin:${PATH}"
|
|
52
|
+
ENV SIGNAL_CLI_DATA=/var/lib/signal-cli
|
|
53
|
+
RUN mkdir -p "${SIGNAL_CLI_DATA}"
|
|
54
|
+
|
|
55
|
+
EXPOSE 8080
|
|
56
|
+
|
|
57
|
+
# Bound to 0.0.0.0 so the Host-header pin is skipped for in-network callers
|
|
58
|
+
# (HttpServerHandler.isHostAllowed). The container only ever sits on the sealed
|
|
59
|
+
# e2e network.
|
|
60
|
+
CMD ["signal-cli", "--config", "/var/lib/signal-cli", "daemon", "--http", "0.0.0.0:8080"]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# The signal-cli release host — the sim internet's stand-in for the GitHub
|
|
2
|
+
# releases the signal module downloads at deploy time.
|
|
3
|
+
#
|
|
4
|
+
# Same reason npm-registry-sim and apt-repo-sim exist: a module that fetches an
|
|
5
|
+
# artifact from the internet must still be deployable inside a sealed network,
|
|
6
|
+
# and the honest way to test that is to SERVE the artifact rather than to skip
|
|
7
|
+
# the download. The module points at this host through its `release_base_url`
|
|
8
|
+
# config, exactly as caddy points at pebble through the ACME directory URL.
|
|
9
|
+
#
|
|
10
|
+
# The tarball is fetched at BUILD time on the builder's own architecture (the
|
|
11
|
+
# e2e network is sealed at run time, and extracting under qemu on an arm64 host
|
|
12
|
+
# fails — see Dockerfile.signal-cli for the full account).
|
|
13
|
+
|
|
14
|
+
ARG SIGNAL_CLI_VERSION=0.14.6
|
|
15
|
+
|
|
16
|
+
FROM --platform=$BUILDPLATFORM debian:bookworm-slim AS fetch
|
|
17
|
+
ARG SIGNAL_CLI_VERSION
|
|
18
|
+
RUN apt-get update \
|
|
19
|
+
&& apt-get install -y --no-install-recommends curl ca-certificates \
|
|
20
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
21
|
+
# The portable JVM distribution, NOT the "-Linux-native" build: that one is a
|
|
22
|
+
# compiled x86_64 binary and cannot run on aarch64 at all. The JAR plus a JRE
|
|
23
|
+
# plus our own libsignal native works on both architectures.
|
|
24
|
+
#
|
|
25
|
+
# Served at the path BELOW the base URL, not GitHub's full path: the
|
|
26
|
+
# production default (`.../AsamK/signal-cli/releases/download`) already carries
|
|
27
|
+
# that prefix, so the module appends only `/v<version>/<file>`. Mirroring
|
|
28
|
+
# GitHub's full layout here would 404 for exactly that reason.
|
|
29
|
+
RUN mkdir -p "/out/v${SIGNAL_CLI_VERSION}" \
|
|
30
|
+
&& curl -fsSL \
|
|
31
|
+
"https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}.tar.gz" \
|
|
32
|
+
-o "/out/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}.tar.gz"
|
|
33
|
+
|
|
34
|
+
FROM nginx:alpine
|
|
35
|
+
COPY --from=fetch /out /usr/share/nginx/html
|
|
36
|
+
|
|
37
|
+
# Route the customer's public prefix via the ISP edge, like every other host on
|
|
38
|
+
# internet-external. See config/routing/public-sim-entrypoint.sh. (Alpine's
|
|
39
|
+
# busybox already provides `ip`, so nothing to install.)
|
|
40
|
+
COPY config/routing/public-sim-entrypoint.sh /usr/local/bin/public-sim-entrypoint.sh
|
|
41
|
+
|
|
42
|
+
EXPOSE 80
|
|
43
|
+
ENTRYPOINT ["/bin/sh", "/usr/local/bin/public-sim-entrypoint.sh"]
|
|
44
|
+
CMD ["nginx", "-g", "daemon off;"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# The signal-cli SIMULATOR — not the real daemon.
|
|
2
|
+
#
|
|
3
|
+
# Dockerfile.signal-cli runs the actual signal-cli binary and exists to keep
|
|
4
|
+
# our understanding of its JSON-RPC surface honest (the pebble pattern). This
|
|
5
|
+
# image is the fast, drivable stand-in used by tests that need to control what
|
|
6
|
+
# arrives: it can queue an inbound reply, fail a recipient inside a success,
|
|
7
|
+
# and revoke the device link on demand — none of which the real unlinked
|
|
8
|
+
# daemon can be made to do.
|
|
9
|
+
FROM oven/bun:1
|
|
10
|
+
|
|
11
|
+
WORKDIR /app
|
|
12
|
+
COPY simulators/signal-cli/server.ts ./server.ts
|
|
13
|
+
|
|
14
|
+
ENV SIGNAL_RPC_PORT=8080
|
|
15
|
+
|
|
16
|
+
EXPOSE 8080
|
|
17
|
+
CMD ["bun", "run", "server.ts"]
|