This guide covers a practical self-hosted setup for Codex Mobile Console.
Install Node.js 20+ and Codex CLI on the server.
Verify:
node --version
codex --version
codex doctorMake sure Codex is already authenticated and works from the same user that will run the service.
For a fresh Linux server:
curl -fsSL https://welcome.ai.hehao.pro/install.sh | bashDefaults:
| Setting | Value |
|---|---|
| Install directory | /opt/codex-mobile-console |
| Service | codex-mobile-console |
| Host | 127.0.0.1 |
| Port | 7072 |
| Project browser root | $HOME/Projects |
Override values:
curl -fsSL https://welcome.ai.hehao.pro/install.sh | \
INSTALL_DIR=/srv/codex-mobile-console \
PORT=7072 \
PROJECTS_ROOT=/root/Projects \
bashThe installer prints the local URL and generated password after startup.
The systemd service runs as the user who executed the installer. This is important because Codex authentication usually lives under that user's home directory. Defaults derived from the install user:
| Setting | Example |
|---|---|
HOME |
/root or /home/alice |
CODEX_HOME |
$HOME/.codex |
PROJECTS_ROOT |
$HOME/Projects |
If Codex is authenticated as a different user, either run the installer as that user or pass explicit values:
curl -fsSL https://welcome.ai.hehao.pro/install.sh | \
CODEX_HOME=/root/.codex \
PROJECTS_ROOT=/root/Projects \
bashOptional Caddy reverse proxy and HTTPS setup:
curl -fsSL https://welcome.ai.hehao.pro/install.sh | DOMAIN=codex.example.com SETUP_CADDY=1 bashBefore running it, point codex.example.com to the server's public IP. The installer keeps the app bound to 127.0.0.1:7072, installs Caddy when possible, writes a managed Caddyfile block, validates the config, and reloads Caddy. If port 80 or 443 is already owned by another non-Caddy service, the installer stops with a clear error instead of replacing that service.
Optional bare public-IP setup:
curl -fsSL https://welcome.ai.hehao.pro/install.sh | PUBLIC_BIND=1 bashThis mode binds the app directly to 0.0.0.0:7072 and skips Caddy. It is useful for quick testing on a server IP, but you should restrict access with firewall/security group rules and move to HTTPS when possible.
git clone https://github.com/twotwo7/codex-mobile-console.git
cd codex-mobile-console
npm install
COOKIE_SECURE=0 npm startThe app defaults to:
http://127.0.0.1:7072
The first generated password is stored in:
cat data/admin-password.txtChange it by editing that file and restarting the service.
COOKIE_SECURE=0 is only for local HTTP testing. Keep the default Secure cookie behavior when serving through HTTPS.
From the project root:
sudo ./scripts/install-systemd.sh
sudo systemctl enable --now codex-mobile-console
sudo systemctl status codex-mobile-console --no-pagerOverride values when needed:
sudo SERVICE_NAME=codex-mobile-console \
HOST=127.0.0.1 \
PORT=7072 \
CODEX_BIN=/usr/bin/codex \
CODEX_HOME=/root/.codex \
PROJECTS_ROOT=/root/Projects \
SERVICE_USER=root \
SERVICE_GROUP=root \
SERVICE_HOME=/root \
./scripts/install-systemd.shThe service intentionally binds to 127.0.0.1 by default. Use a reverse proxy for public access.
Caddy is the simplest option when the domain already points at the server.
Example /etc/caddy/Caddyfile:
codex.example.com {
reverse_proxy 127.0.0.1:7072
}Reload:
sudo systemctl reload caddyThen open:
https://codex.example.com
Example Nginx server block:
server {
listen 80;
server_name codex.example.com;
location / {
proxy_pass http://127.0.0.1:7072;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Then use Certbot or your existing certificate workflow to enable HTTPS.
The app can have active Codex child processes. Prefer safe restart:
./scripts/safe-restart.shIf Codex is running, the API may queue the restart instead of hard killing the active process.
For system-level waiting:
./scripts/queue-safe-restart.shLogs:
tail -f runtime/safe-restart.logcurl -fsS http://127.0.0.1:7072/api/healthzExpected:
{"ok":true}- Use HTTPS for phone access.
- Keep
HOST=127.0.0.1when using a reverse proxy. - Store the admin password in
data/admin-password.txtwith mode0600. - Do not commit
data/,runtime/,.env, or token files. - Avoid exposing this app on an untrusted public network.
- Consider adding VPN, Cloudflare Access, Tailscale, or another access layer.