Instagram Reply Bot
Self-hosted Instagram DM and comment auto-reply appliance with a web panel, lead forms and a built-in catalog.
The Instagram Reply Bot is a self-hosted appliance that answers Instagram direct messages and comments on your behalf, around the clock, from a server you control. It is deployed as a single Go binary behind nginx with a Let's Encrypt certificate, and is managed entirely through its own web panel — no database server, no container runtime and no external SaaS sits between your account and your customers.
Everything the bot stores — conversation rules, form submissions, catalog items and uploaded media — stays on your own instance. The only outbound calls it makes are to Meta's Graph API and, when you enable AI replies, to the language-model provider you configure.
Instagram Reply Bot. Key features
- Rule-based auto-replies for direct messages — exact, contains and keyword matching with a configurable fallback
- Comment-to-DM: reply publicly under a post and send the full answer privately at the same time
- Optional AI replies backed by a language model, with the rule engine still handling anything you have answered explicitly
- Follow gate — require a follow before the bot hands over a link, code or file
- Lead forms with multi-step flows and one-click CSV export of every submission
- Built-in mini catalog so customers can browse products and prices inside the DM thread
- Scheduled follow-ups for people who opened a conversation and went quiet
- Welcome / "Send message" start flow for first-time visitors
- Multi-user panel with admin and operator roles, bilingual in English and Persian
- Signed automatic updates — every package is verified against an Ed25519 key before it is installed
- Hardened systemd unit: dedicated service user, no new privileges, read-only system paths
Deployment features
| Software ID | 1 |
|---|---|
| Compatible OS | Debian 13Debian 12Ubuntu 24.04Ubuntu 22.04 |
| Hardware | Virtual machine: yes Bare metal: yes vGPU: no GPU: no |
| Minimum requirements | 1 vCPU · 1 GB · 10 GB NVMe |
| Custom domain | Required |
| Licence | Proprietary — included with the server |
| Status | Active |
| Last updated |
Getting started after deploying
Order the appliance with a domain name in hand — the installer needs an A
record pointing at your server before it can issue a TLS certificate. Once the server is
provisioned you will receive its IP address and root credentials by email.
Point your subdomain at the server first, for example bot.example.com → your.server.ip,
then connect over SSH and run the installer:
curl -fsSL https://updates.karizanta.com/install.sh | bash -s -- \
--domain bot.example.com --email you@example.com
The installer performs the whole setup in one pass:
- Verifies that the domain resolves to this server, and stops before touching anything if it does not.
- Installs nginx, certbot and the supporting tools.
- Creates the
igbotservice user and/opt/igbot. - Downloads the latest release and checks its SHA-256 checksum and its Ed25519 signature.
- Writes the nginx vhost and obtains a Let's Encrypt certificate.
- Registers a hardened systemd unit with automatic restart.
- Prints your panel URL and the generated admin password.
Useful flags:
--channel beta # install from the pre-release channel
--dir /srv/igbot # install somewhere other than /opt/igbot
--instance shopname # run a second, fully separate install on the same server
--dry-run # show what would happen, change nothing
The installer is safe to re-run: an existing .env, your rules and your
uploads are left untouched. If it finds an installation already serving a
different domain it stops rather than overwriting it — pass --force
only when replacing that install is genuinely what you want.
Signing in to the panel
Open https://bot.example.com/panel and sign in as admin with the
password printed at the end of the install. Change it under Account before
you do anything else; the generated password was printed to your terminal and to the install
log, so it should not remain the long-term credential.
The service deliberately does not start until the Instagram connection is filled in — an unconfigured bot that answers nobody is safer than one that starts up half-wired.
Connecting your Instagram account
The bot talks to Instagram through a Meta app. Your account must be a Professional / Business account (Creator accounts have messaging restrictions), which you can switch to from the Instagram mobile app under Settings → Account type and tools.
- At developers.facebook.com create an app and pick the Instagram messaging use case.
- Under Instagram → API setup, add your business account and generate an access token. Convert the short-lived token into a long-lived one (60 days, renewable — the bot refreshes it for you afterwards).
- Copy App settings → Basic → App secret.
- Paste all four values into the panel under Connection, or straight
into
/opt/igbot/.env:
META_APP_SECRET=...
META_PAGE_TOKEN=...
IG_USER_ID=...
META_VERIFY_TOKEN=... # generated for you by the installer
Then start the service and confirm it is healthy:
systemctl start igbot
curl https://bot.example.com/healthz # -> ok
Registering the webhook
In the Meta app, open Instagram → Configure webhooks and enter:
| Callback URL | https://bot.example.com/webhook |
|---|---|
| Verify Token | the META_VERIFY_TOKEN from your .env |
| Subscribed fields | messages — add comments to enable comment-to-DM |
Press Verify and save. A successful handshake is visible in the log:
journalctl -u igbot -n 20
While the Meta app is in Development mode only accounts you have added as testers can reach the bot. Serving real customers requires App Review and Business Verification, which typically takes one to three weeks.
Configuring replies
Rules live under Rules in the panel and are stored in
/opt/igbot/rules.json. Each rule has a match mode — exact,
contains or keyword — a list of patterns and a reply. Anything that matches
no rule gets the fallback message, which is the right place to put a short numbered menu.
The panel includes a rule tester: paste a message a customer might send and see which rule would win before it ever reaches a real conversation.
Beyond plain replies you can enable:
- Forms — multi-step questions whose answers land under Submissions and export to CSV.
- Catalog — products with images and prices, browsable in the thread and
on a public
/shoppage. - Follow gate — hold a link or discount code back until the person follows the account.
- Follow-ups — a scheduled nudge to people who stopped replying.
The 24-hour window
Meta only allows free-form replies within 24 hours of the customer's last message. After that, only approved message templates go through. This is a platform rule, not a limitation of the appliance — build your flows so the useful answer arrives in the first exchange rather than a day later.
Updating and rolling back
Each installation checks the release channel every six hours and can be updated from Updates in the panel. Update packages are verified against a checksum and an Ed25519 signature before they are installed, so a compromised network path cannot hand your server a different binary.
The previous binary is kept, which makes a rollback two commands:
systemctl stop igbot
mv /opt/igbot/igbot.prev /opt/igbot/igbot
systemctl start igbot
Files on the server
/opt/igbot/.env | configuration and secrets (mode 0600) |
|---|---|
/opt/igbot/rules.json | reply rules — edited from the panel |
/opt/igbot/users.json | panel users (bcrypt hashes) |
/opt/igbot/token.json | the refreshed long-lived token |
/opt/igbot/stats.json | message and reply counters |
/opt/igbot/igbot.prev | the previous binary, kept for rollback |
A backup of the appliance is those files plus the public/ uploads directory.
Nothing else on the server holds state.
Troubleshooting
| Symptom | What to check |
|---|---|
| Service will not start | journalctl -u igbot -n 50 — almost always an incomplete .env |
| Webhook verification fails | Service down, verify token mismatch, or the certificate is not yet issued |
| No webhooks arrive at all | The messages field is not subscribed, or the app is still in Development mode |
| Messages arrive but no reply is sent | Expired token, or the 24-hour window has closed |
| "Application does not have permission" | The account is not a Business account, or messaging permissions were not granted |
| An update is refused | Signature mismatch — the package was tampered with or the signing key changed |
Frequently asked questions
Do I need a domain name?
Yes. Meta only accepts HTTPS webhook endpoints with a valid certificate, so the installer
needs a domain with an A record pointing at the server in order to issue one.
Can one server run bots for several Instagram accounts?
Yes. Run the installer again with --instance name and a second domain. Each
instance gets its own service user, directory, port and configuration, and they share
nothing.
Does it work without an AI provider?
Yes. The rule engine is the default and needs no API key at all. AI replies are an optional layer for messages that no rule covers.
What happens to my data?
It stays on your server. Rules, submissions, catalog items and uploads are plain files under the install directory; nothing is sent to Karizanta.
Can I move the installation to another server?
Yes. Run the installer on the new server, stop the service, copy the JSON files and the
public/ directory across, update the DNS record and start it again.
Something out of date or unclear in this guide? Let us know — it is maintained by the team that builds the image.
