revs412@portfolio:~/notes/running-discord-bot-on-openwrt$cat running-discord-bot-on-openwrt.md

Why This Note Exists

OpenWrt is usually treated as router firmware, not as a general application server.

But on capable hardware, it can run small internal services if the setup is kept simple and maintainable. A Discord bot is a good example of a small service that can run continuously without needing a full VPS.

This note documents the practical side of running a small Node.js Discord bot on OpenWrt: where to place the files, how to handle environment variables, how to run it as a service, how to restart it, and how to debug common deployment issues.

The point is not that the bot runs on OpenWrt because that is impressive. The point is learning how to operate a small service on constrained infrastructure without losing track of logs, secrets, updates, and restarts.

Device Context

The setup is based on an OpenWrt device used as both network infrastructure and a lightweight service host.

In this kind of setup, the router is already important. Adding application services means extra care is needed.

The service should not make the router harder to maintain, and bot failures should not affect routing, DNS, VPN, or firewall behavior.

What This Setup Is Meant To Prove

  • small services can run on OpenWrt when the device has enough resources
  • router-hosted services need clean restart and log handling
  • environment variables should not be hardcoded in source code
  • Docker can make updates cleaner, but it adds its own operational layer
  • OpenWrt procd can run services directly when Docker is not needed
  • deployment scripts reduce repeated manual commands
  • logs are essential because silent bot failures are common
  • service hosting on a router should stay deliberate and limited

Stack and Tools Used

Application Layer

  • Node.js
  • discord.js
  • JavaScript
  • environment variables
  • bot token configuration
  • command/event handling

OpenWrt Layer

  • SSH
  • LuCI where useful
  • package management
  • filesystem paths under /opt
  • service management
  • logs through OpenWrt tooling
  • storage/overlay awareness

Deployment Layer

  • Docker, optional
  • procd, optional
  • .env.local or equivalent environment file
  • build/run/stop/restart scripts
  • Git-based or copy-based update workflow
  • SCP/rsync or other sync method

Troubleshooting Layer

  • container logs
  • service logs
  • process checks
  • environment file checks
  • Discord command registration checks
  • network/DNS time validation

Intended Build

The intended build is a small bot service that can run continuously on OpenWrt and be maintained without manually repeating a long set of commands every time.

A finished setup should allow:

  • source code stored in a clear directory
  • secrets stored outside the code
  • predictable start/stop/restart
  • logs available when the bot fails
  • easy rebuild or redeploy
  • clear update workflow from development machine to OpenWrt
  • service recovery after reboot
  • minimal impact on core router functions

Directory Layout

A clean layout is important.

Example direction:

/opt/discord-bots/
  bot-name/
    package.json
    src/
    .env.local
    scripts/

The exact bot name can change, but the principle stays the same:

  • application files live in one known directory
  • secrets are not committed publicly
  • scripts live near the project
  • logs are easy to reach
  • deployment path is documented

Environment Variables

Secrets should not be hardcoded.

A local environment file can store values like:

DISCORD_TOKEN=
CLIENT_ID=
GUILD_ID=
NODE_ENV=production

The bot should load the environment file at startup.

Important checks:

  • the file exists on OpenWrt
  • the service/container can read it
  • the variable names match the code
  • the token is not printed in logs
  • the file is not committed to a public repository

A missing or unreadable env file is one of the easiest ways for a bot to fail after deployment.

Running Directly With Node.js

One direction is to run the bot directly with Node.js installed on OpenWrt.

This keeps the setup simple, but it depends on the OpenWrt package environment and installed Node.js version.

Basic manual shape:

node src/index.js

For production, manual execution is not enough. The bot needs to run as a managed service.

Running With OpenWrt procd

OpenWrt services normally use procd.

A procd service can:

  • start the bot at boot
  • restart it if it crashes
  • capture stdout/stderr
  • make start/stop/restart easier
  • integrate with OpenWrt service commands

Example service shape:

#!/bin/sh /etc/rc.common

START=99
STOP=10
USE_PROCD=1

APP_DIR="/opt/discord-bots/bot-name"

start_service() {
  procd_open_instance
  procd_set_param command /usr/bin/node "$APP_DIR/src/index.js"
  procd_set_param env NODE_ENV=production
  procd_set_param respawn 3600 5 5
  procd_set_param stdout 1
  procd_set_param stderr 1
  procd_close_instance
}

This should be adjusted to the real project path and environment loading method.

Running With Docker

Docker is useful when you want a more consistent runtime.

A Docker setup can define the Node.js version, dependencies, environment file usage, and restart behavior more cleanly.

Example direction:

Dockerfile
.env.local
docker build
docker run --env-file .env.local

For OpenWrt, Docker support depends on device resources, storage, kernel support, and package availability.

Docker makes application packaging cleaner, but it also adds:

  • image rebuilds
  • container cleanup
  • volume/env handling
  • container logs
  • networking decisions
  • storage usage

Docker Network Choice

For a small bot, host networking may be simple:

--network host

This avoids some container network complexity, but it should be used intentionally.

The bot usually only needs outbound access to Discord, so it does not need public inbound ports.

Service and Container Management

A useful deployment should include scripts for common actions.

Examples:

build
run
stop
restart
logs
status
clean
help

The goal is to avoid remembering long Docker or service commands manually.

A helper script should be clear enough that future updates are not painful.

Deployment Workflow

A practical workflow looks like this:

  1. edit code on the development machine
  2. test locally where possible
  3. sync files to OpenWrt
  4. install dependencies or rebuild container
  5. restart the service/container
  6. check logs
  7. verify the bot is online
  8. test one real command/action

File syncing can use:

  • scp
  • rsync
  • Git pull if available
  • manual upload for small changes

The exact method matters less than consistency.

Common Failure Points

Bot Starts Locally but Not on OpenWrt

Likely causes:

  • wrong Node.js version
  • missing dependencies
  • wrong working directory
  • missing .env.local
  • file permissions
  • OpenWrt path differences
  • service not loading environment variables

Container Builds but Does Not Run

Likely causes:

  • wrong image architecture
  • missing command
  • missing env file
  • wrong container name
  • old container already exists
  • dependency install failure
  • application exits immediately

Useful checks:

docker ps -a
docker logs <container-name>

Bot Is Online but Slash Commands Are Wrong

Likely causes:

  • command registration not redeployed
  • duplicate command names
  • commands registered globally but expected instantly
  • old commands still cached
  • wrong application/client ID
  • wrong guild ID
  • bot lacks permissions

Service Runs but Logs Are Missing

Likely causes:

  • stdout/stderr not captured
  • service file does not enable logging
  • container logs not checked
  • application catches errors silently
  • process exits before logging

Time or Certificate Errors

A device with wrong system time can cause TLS/certificate problems.

Symptoms may look unrelated, such as network requests failing even though DNS and internet access work.

Useful checks:

date
logread | grep -i cert

If time is wrong, fix NTP/time sync first.

Practical Decisions

Keep the router’s main job protected

The router should still be a router first.

If the bot becomes heavy, unstable, or complicated, it may be better to move it to a small server or VPS.

Do not hardcode secrets

Tokens and IDs should live in environment files or secret handling, not inside code.

Use scripts for repeated actions

If a command is repeated often, make it a script.

This reduces mistakes during rebuilds, restarts, and cleanup.

Prefer clear logs over silent restarts

A service that restarts automatically but gives no useful logs is hard to maintain.

Logs should make failures obvious.

Avoid exposing ports unnecessarily

Most Discord bots only need outbound access.

Do not open public ports unless the bot runs a web server or webhook listener that actually needs inbound traffic.

Keep one clean source of deployment truth

Avoid having multiple half-working deployment methods at the same time.

If Docker is used, make Docker the main path. If procd direct Node.js is used, make that the main path.

What A Finished Setup Should Show

A strong finished setup should show:

  • bot source files in a clear directory
  • environment file present and protected
  • service/container starts reliably
  • restart workflow documented
  • logs available
  • bot comes online after reboot or restart
  • deployment/update script available
  • command registration understood
  • no unnecessary public ports exposed
  • router core functions unaffected
  • cleanup process for old containers/images if using Docker

Evidence Worth Capturing

Useful evidence for this note would include:

  • directory layout screenshot or tree
  • service file example
  • Dockerfile
  • helper script
  • .env.example without real secrets
  • docker ps output
  • service status output
  • log examples
  • bot online screenshot
  • command test screenshot
  • restart test
  • notes about failures and fixes

Technical Assumptions

This setup assumes the OpenWrt device has enough CPU, RAM, and storage for the bot and runtime.

It also assumes that the bot is small and mostly event/command based, not a heavy application.

The setup assumes that internet access, DNS, and system time are stable, because Discord API access depends on all three.

Key Risks

  • router overloaded by application services
  • secrets accidentally committed or printed
  • bot failing silently after restart
  • old containers conflicting with new ones
  • wrong architecture image
  • missing environment variables
  • storage filling up with images/logs
  • DNS/time issues causing API failures
  • command registration confusion
  • no clean rollback after a broken update

Current State

This note represents the deployment and maintenance direction for running a small Discord bot on OpenWrt.

The important lesson is that even a small bot needs operational structure when it runs continuously: environment files, service management, restart behavior, logs, and repeatable deployment steps.

This connects directly to other notes about OpenWrt, Docker scripts, DNS, and service troubleshooting.

What This Note Does Not Claim

This note does not claim that OpenWrt is always the best place to host bots.

It does not claim that router-hosted services are suitable for every production workload.

It does not claim that Docker is mandatory.

The project is best understood as a practical deployment note for small services on constrained infrastructure.

Practical Takeaway

Running a bot on OpenWrt is not mainly about starting node index.js.

The useful part is the operational structure around it:

  • where the files live
  • how secrets are loaded
  • how it starts after reboot
  • how it restarts after failure
  • where logs are read
  • how updates are deployed
  • how to clean up broken containers
  • how to avoid affecting the router’s main job

That is what makes the setup maintainable.