Skip to content

Commit 1abee12

Browse files
committed
Add Oracle Cloud deployment setup
Add deploy/oracle with an Oracle-ready docker-compose that builds this fork for the VM's native (ARM64) architecture, runs the logviewer, and reuses the existing MongoDB via CONNECTION_URI. Includes a host setup script (Docker install + firewall) and a step-by-step migration guide. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013vqQJQAud7rmfykwWKJACY
1 parent b4be6be commit 1abee12

4 files changed

Lines changed: 207 additions & 0 deletions

File tree

deploy/oracle/.env.example

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copy this file to `.env` in the same directory and fill in your values.
2+
# cp .env.example .env && nano .env
3+
4+
# Your Discord bot token.
5+
TOKEN=MyBotToken
6+
7+
# The ID of the Discord server (guild) this bot serves.
8+
GUILD_ID=1234567890
9+
10+
# Comma-separated user IDs allowed to run owner-only commands.
11+
OWNERS=Owner1ID,Owner2ID
12+
13+
# Your EXISTING MongoDB connection URI (kept from your previous host).
14+
# The logviewer reuses this same URI via MONGO_URI in docker-compose.yml.
15+
CONNECTION_URI=mongodb+srv://user:pass@cluster.mongodb.net/modmail
16+
17+
# Public URL where the logviewer is reachable, used in generated log links.
18+
# Set this to your VM's public IP (or domain) on port 8000, e.g.:
19+
# http://123.45.67.89:8000
20+
LOG_URL=http://YOUR_VM_PUBLIC_IP:8000

deploy/oracle/README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Deploying Modmail to Oracle Cloud
2+
3+
This 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**.
5+
6+
What you get:
7+
- `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+
- No database container — the bot and logviewer both point at your current
11+
`CONNECTION_URI`.
12+
13+
---
14+
15+
## 1. Create the VM
16+
17+
In the [OCI Console](https://cloud.oracle.com/)**Compute → Instances → Create**:
18+
19+
- **Image:** Canonical Ubuntu 22.04 (or Oracle Linux 9).
20+
- **Shape:** `VM.Standard.A1.Flex` (Ampere ARM, **Always Free** — e.g. 1–2 OCPUs,
21+
6–12 GB RAM is plenty).
22+
- **SSH keys:** upload/download a key pair so you can log in.
23+
- Note the instance's **public IP** after it boots.
24+
25+
## 2. Open the firewall (cloud side)
26+
27+
The instance firewall is handled by `setup.sh`, but the cloud network is separate.
28+
29+
In the OCI Console → **Networking → Virtual Cloud Networks → your VCN → your
30+
subnet → Security List → Add Ingress Rules**:
31+
32+
| Source CIDR | Protocol | Dest. Port | Purpose |
33+
|-------------|----------|------------|---------------|
34+
| `0.0.0.0/0` | TCP | `8000` | Logviewer |
35+
36+
(Port `22` for SSH is usually open by default.)
37+
38+
## 3. Install Docker on the VM
39+
40+
SSH in, then:
41+
42+
```bash
43+
ssh ubuntu@YOUR_VM_PUBLIC_IP # or opc@... on Oracle Linux
44+
45+
# Get this fork's deploy files:
46+
git clone https://github.com/PloverRoblox/modmail.git
47+
cd modmail
48+
git checkout claude/gifted-curie-z2wprx
49+
cd deploy/oracle
50+
51+
chmod +x setup.sh && ./setup.sh
52+
```
53+
54+
Then **log out and back in** so your user picks up the `docker` group.
55+
56+
## 4. Configure your environment
57+
58+
```bash
59+
cp .env.example .env
60+
nano .env
61+
```
62+
63+
Fill in:
64+
- `TOKEN`, `GUILD_ID`, `OWNERS` — same values as your old host.
65+
- `CONNECTION_URI` — your **existing** MongoDB URI (nothing migrates; the bot
66+
just reconnects to the same database).
67+
- `LOG_URL``http://YOUR_VM_PUBLIC_IP:8000`
68+
69+
## 5. Launch
70+
71+
```bash
72+
docker compose up -d --build
73+
docker compose logs -f bot # watch it connect to Discord
74+
```
75+
76+
You should see the bot log in. Closed-thread log links will resolve at
77+
`http://YOUR_VM_PUBLIC_IP:8000`.
78+
79+
## 6. Decommission the old host
80+
81+
Once the new instance is confirmed working, stop the bot on your previous host
82+
so two instances don't run against the same database at once.
83+
84+
---
85+
86+
## Updating later
87+
88+
```bash
89+
cd ~/modmail && git pull
90+
cd deploy/oracle && docker compose up -d --build
91+
```
92+
93+
## Troubleshooting
94+
95+
- **Bot won't start / DB errors:** double-check `CONNECTION_URI` and that your
96+
MongoDB/Atlas network access list allows the VM's public IP.
97+
- **Logviewer container exits with "exec format error" on the ARM VM:** the
98+
upstream `logviewer` image may not publish an `arm64` variant. Two fixes:
99+
1. Add emulation, then retry:
100+
`sudo apt install -y qemu-user-static binfmt-support` and add
101+
`platform: linux/amd64` under the `logviewer` service in
102+
`docker-compose.yml`; **or**
103+
2. Use an x86 shape (`VM.Standard.E2.1.Micro`, also Always Free) for the VM so
104+
the upstream image runs natively.
105+
- **Can't reach the logviewer in a browser:** confirm both the OCI Security List
106+
rule (step 2) *and* the instance firewall (`setup.sh`) allow port `8000`.
107+
```

deploy/oracle/docker-compose.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Oracle Cloud deployment for Modmail (this fork) + Logviewer.
2+
#
3+
# - `bot` is built from this repository's Dockerfile so your fork's changes are
4+
# included, and so the image is native to the host architecture (the Always
5+
# Free Ampere A1 VM is ARM64 / aarch64).
6+
# - `logviewer` is pulled from the upstream registry. If it fails to start on an
7+
# ARM VM (manifest/exec format error), see the note in README.md.
8+
# - There is no `mongo` service here: this setup points at your EXISTING database
9+
# via CONNECTION_URI in .env (your current MongoDB / Atlas URI).
10+
11+
services:
12+
bot:
13+
build:
14+
context: ../..
15+
dockerfile: Dockerfile
16+
image: modmail-fork:latest
17+
container_name: modmail-bot
18+
restart: always
19+
env_file:
20+
- .env
21+
22+
logviewer:
23+
image: ghcr.io/modmail-dev/logviewer:master
24+
container_name: modmail-logviewer
25+
restart: always
26+
env_file:
27+
- .env
28+
environment:
29+
# Logviewer reads MONGO_URI; reuse the same database the bot writes to.
30+
- MONGO_URI=${CONNECTION_URI}
31+
ports:
32+
- "8000:8000"

deploy/oracle/setup.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env bash
2+
#
3+
# One-time host setup for running Modmail on an Oracle Cloud VM.
4+
# Installs Docker + Compose and opens the logviewer port (8000) on the instance
5+
# firewall. Works on Ubuntu (apt) and Oracle Linux (dnf) images.
6+
#
7+
# Usage (run on the VM):
8+
# chmod +x setup.sh && ./setup.sh
9+
#
10+
# NOTE: This handles the *instance* firewall only. You must ALSO open port 8000
11+
# (and 22 for SSH) in the OCI Console -> VCN -> Security List. See README.md.
12+
13+
set -euo pipefail
14+
15+
LOGVIEWER_PORT=8000
16+
17+
echo "==> Installing Docker Engine + Compose plugin..."
18+
if ! command -v docker >/dev/null 2>&1; then
19+
curl -fsSL https://get.docker.com | sh
20+
fi
21+
22+
echo "==> Adding current user to the docker group (re-login to take effect)..."
23+
sudo usermod -aG docker "$USER" || true
24+
25+
echo "==> Enabling and starting Docker..."
26+
sudo systemctl enable --now docker
27+
28+
echo "==> Opening instance firewall on port ${LOGVIEWER_PORT}..."
29+
if command -v firewall-cmd >/dev/null 2>&1; then
30+
# Oracle Linux ships firewalld.
31+
sudo firewall-cmd --permanent --add-port=${LOGVIEWER_PORT}/tcp
32+
sudo firewall-cmd --reload
33+
elif command -v iptables >/dev/null 2>&1; then
34+
# Ubuntu Oracle images ship a restrictive iptables ruleset.
35+
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport ${LOGVIEWER_PORT} -j ACCEPT
36+
if command -v netfilter-persistent >/dev/null 2>&1; then
37+
sudo netfilter-persistent save
38+
else
39+
echo " (Install iptables-persistent to make this rule survive reboot.)"
40+
fi
41+
fi
42+
43+
echo ""
44+
echo "==> Host setup complete."
45+
echo " 1. Log out and back in (so the docker group applies)."
46+
echo " 2. cp .env.example .env && edit .env with your values."
47+
echo " 3. docker compose up -d --build"
48+
echo " 4. Make sure port ${LOGVIEWER_PORT} is also open in the OCI Security List."

0 commit comments

Comments
 (0)