11# Deploying Modmail to Oracle Cloud
22
33This guide moves your Modmail bot (this fork) and the Logviewer onto an Oracle
4- Cloud ** Always Free** VM, while continuing to use your ** existing MongoDB** .
4+ Cloud ** Always Free** VM, while continuing to use your ** existing MongoDB** . The
5+ logviewer is published on your own domain via a ** Cloudflare Tunnel** , so no
6+ inbound ports are exposed.
57
68What you get:
79- ` bot ` — built from this repo's ` Dockerfile ` , so your fork's changes are
8- included and the image is native to the VM's ARM64 architecture.
9- - ` logviewer ` — the web UI for closed-thread log links, served on port ` 8000 ` .
10+ included and the image is native to the VM's architecture.
11+ - ` logviewer ` — the web UI for closed-thread log links.
12+ - ` cloudflared ` — a Cloudflare Tunnel that serves the logviewer at your domain
13+ over HTTPS, with no open ports on the VM.
1014- No database container — the bot and logviewer both point at your current
1115 ` CONNECTION_URI ` .
1216
@@ -23,20 +27,26 @@ In the [OCI Console](https://cloud.oracle.com/) → **Compute → Instances →
2327 - ` VM.Standard.E2.1.Micro ` (x86, 1 OCPU / 1 GB RAM) — logviewer runs natively;
2428 ` setup.sh ` adds a swap file to handle the 1 GB limit during image builds.
2529- ** SSH keys:** upload/download a key pair so you can log in.
26- - Note the instance's ** public IP** after it boots.
2730
28- ## 2. Open the firewall (cloud side)
31+ With a Cloudflare Tunnel you do ** not** need to open any ingress ports in the OCI
32+ Security List — the tunnel connects outbound. (Port ` 22 ` for SSH is open by
33+ default.)
2934
30- The instance firewall is handled by ` setup.sh ` , but the cloud network is separate.
35+ ## 2. Create the Cloudflare Tunnel
3136
32- In the OCI Console → ** Networking → Virtual Cloud Networks → your VCN → your
33- subnet → Security List → Add Ingress Rules ** :
37+ In the [ Cloudflare Zero Trust dashboard ] ( https://one.dash.cloudflare.com/ ) →
38+ ** Networks → Tunnels ** :
3439
35- | Source CIDR | Protocol | Dest. Port | Purpose |
36- | -------------| ----------| ------------| ---------------|
37- | ` 0.0.0.0/0 ` | TCP | ` 8000 ` | Logviewer |
38-
39- (Port ` 22 ` for SSH is usually open by default.)
40+ 1 . ** Create a tunnel** → choose ** Cloudflared** → give it a name (e.g. ` modmail ` ).
41+ 2 . On the install screen, ** copy the tunnel token** — it's the long string in the
42+ shown ` cloudflared ... run <TOKEN> ` command. You don't run that command; the
43+ ` cloudflared ` container uses the token. Save it for step 4.
44+ 3 . Add a ** Public Hostname** :
45+ - ** Subdomain / Domain:** e.g. ` logs ` + your Cloudflare-managed domain.
46+ - ** Type:** ` HTTP `
47+ - ** URL:** ` logviewer:8000 ` (the container name + port — they share the
48+ Docker network)
49+ 4 . Save. Cloudflare auto-creates the DNS record and HTTPS cert for that hostname.
4050
4151## 3. Install Docker on the VM
4252
@@ -67,17 +77,19 @@ Fill in:
6777- ` TOKEN ` , ` GUILD_ID ` , ` OWNERS ` — same values as your old host.
6878- ` CONNECTION_URI ` — your ** existing** MongoDB URI (nothing migrates; the bot
6979 just reconnects to the same database).
70- - ` LOG_URL ` — ` http://YOUR_VM_PUBLIC_IP:8000 `
80+ - ` LOG_URL ` — your tunnel hostname, e.g. ` https://logs.yourdomain.com `
81+ - ` TUNNEL_TOKEN ` — the token you copied in step 2.
7182
7283## 5. Launch
7384
7485``` bash
7586docker compose up -d --build
76- docker compose logs -f bot # watch it connect to Discord
87+ docker compose logs -f bot # watch it connect to Discord
88+ docker compose logs cloudflared # should show "Registered tunnel connection"
7789```
7890
79- You should see the bot log in. Closed-thread log links will resolve at
80- ` http://YOUR_VM_PUBLIC_IP:8000 ` .
91+ Open ` https://logs.yourdomain.com ` in a browser — the logviewer should load.
92+ Closed-thread log links will now use that domain .
8193
8294## 6. Decommission the old host
8395
@@ -96,15 +108,15 @@ cd deploy/oracle && docker compose up -d --build
96108## Troubleshooting
97109
98110- ** Bot won't start / DB errors:** double-check ` CONNECTION_URI ` and that your
99- MongoDB/Atlas network access list allows the VM's public IP.
111+ MongoDB/Atlas network access list (Atlas → Network Access) allows the VM's
112+ public IP.
113+ - ** Logviewer domain shows Cloudflare error 502/1033:** the tunnel can't reach
114+ the logviewer. Confirm the Public Hostname URL is exactly ` logviewer:8000 ` ,
115+ and that ` docker compose logs cloudflared ` shows a registered connection.
116+ - ** ` cloudflared ` keeps restarting:** the ` TUNNEL_TOKEN ` is wrong or missing —
117+ re-copy it from the tunnel's install screen.
100118- ** Logviewer container exits with "exec format error" on the ARM VM:** the
101- upstream ` logviewer ` image may not publish an ` arm64 ` variant. Two fixes:
102- 1 . Add emulation, then retry:
103- ` sudo apt install -y qemu-user-static binfmt-support ` and add
104- ` platform: linux/amd64 ` under the ` logviewer ` service in
105- ` docker-compose.yml ` ; ** or**
106- 2 . Use an x86 shape (` VM.Standard.E2.1.Micro ` , also Always Free) for the VM so
107- the upstream image runs natively.
108- - ** Can't reach the logviewer in a browser:** confirm both the OCI Security List
109- rule (step 2) * and* the instance firewall (` setup.sh ` ) allow port ` 8000 ` .
110- ```
119+ upstream ` logviewer ` image may not publish an ` arm64 ` variant. Either add
120+ ` platform: linux/amd64 ` under the ` logviewer ` service (with
121+ ` sudo apt install -y qemu-user-static binfmt-support ` ), or use the
122+ ` VM.Standard.E2.1.Micro ` x86 shape so the image runs natively.
0 commit comments