NEW·bitcoiners-dca — automate your AED-to-BTC stacking·Try free →

Tutorial · ~45 min · Free tier (no payment, no signup)

Self-host bitcoiners-dca

Run the bot yourself on your Pi, Mac mini, Umbrel, or VPS. End-to-end: from git clone to your first auto-withdraw to a hardware wallet.

In this tutorial

  1. What you'll have at the end
  2. Prerequisites
  3. 1. Get the source
  4. 2. Create your exchange API key (TRADE-only)
  5. 3. Configure your strategy
  6. 4. Validate + dry-run
  7. 5. Go live
  8. 6. Auto-withdraw to your hardware wallet
  9. 7. (Optional) Lightning withdrawals
  10. 8. Monitoring + logs
  11. 9. Upgrade to Pro (or stay on Free)
  12. Troubleshooting
  13. Where to get help

What you'll have at the end

By the end of this guide your machine will be running a long-lived Python process that automatically buys BTC on schedule using your exchange API key, logs every trade to a local SQLite database, and (if you enable it) sweeps accumulated sats to your hardware wallet without you touching it.

The Free tier gives you:

Multi-exchange smart routing, advanced overlays (volatility-weighted, time-of-day, drawdown-aware), Lightning auto-withdraw, the funding-rate monitor, and cross-exchange alerts are gated to Pro tier. You can add the Pro license later without re-installing anything — it's the same bot, you just paste a license token.

Prerequisites

You need:

Heads up: the bot ships with dry_run: true on by default. Every trade is simulated until you explicitly flip that switch. Treat the first few cycles as fire-drills — read the logs, confirm the math, then go live.

1. Get the source

The bot is open source under the MIT license. We're finalising the public GitHub mirror — the source is currently in a private Gitea while the API contract stabilises with the first cohort.

During closed beta: request a Docker image + a copy of the source by emailing support@bitcoiners.ae. Public open-source release lands when we exit closed beta (Q4 2026). Then the snippet below becomes the entry point.
# Closed beta — request access first (see note above), then:
git clone https://github.com/jiashanlu/bitcoiners-dca.git
cd bitcoiners-dca

Create your config and data directories:

cp config.example.yaml config.yaml
mkdir -p data reports

We'll edit config.yaml in step 3. First the API key.

2. Create your exchange API key (TRADE-only)

Security rule #1: never give the bot a key with withdrawal permission. Use trade-only / spot-trading scope only. The worst case from a compromised trade-only key is that someone converts your AED into BTC at market — annoying but not catastrophic. A leaked withdraw-enabled key can drain your account.

Pick the exchange you want to DCA on. The bot supports one exchange at a time on Free tier — you can switch later by editing the config.

2a. OKX UAE

  1. Log into okx.com from your UAE-verified account.
  2. Top-right avatar → APICreate V5 API Key.
  3. Name: dca-bot (or anything).
  4. Permissions: tick Read and Trade only. Do NOT tick Withdraw.
  5. IP whitelist: optional but recommended. If your machine has a static IP, paste it. If it's on a home connection, skip this and rely on the key's passphrase.
  6. Set a passphrase you'll remember (OKX calls it the API passphrase — required on every request).
  7. Save the API key, secret, and passphrase. You'll only see the secret once.

You now have three secrets: OKX_API_KEY, OKX_API_SECRET, OKX_API_PASSPHRASE. Keep them somewhere safe.

2b. BitOasis

  1. Log into bitoasis.net.
  2. Top-right → SettingsAPI Token Management.
  3. Click Generate New Token.
  4. Scopes: Read and Trade only.
  5. Copy the Bearer token — BitOasis shows it once.

You now have one secret: BITOASIS_API_TOKEN. BitOasis uses Bearer-token auth, so there's no separate secret/passphrase.

2c. Binance UAE

UAE residents access binance.com via the ADGM-licensed entity. The bot uses the standard Binance API.

  1. Log into binance.com (account verified through Binance UAE).
  2. Top-right avatar → API Management.
  3. Create a System-Generated key (HMAC). Name: dca-bot.
  4. Permissions: Enable Reading + Enable Spot & Margin Trading. Do NOT enable Withdrawals.
  5. Restrict IP if you can.
Pair note: Binance does not list BTC/AED. If you choose Binance, the bot trades BTC/USDT — you need AED → USDT first (via P2P or another exchange). Most UAE users find OKX or BitOasis simpler for a Free-tier setup.

3. Configure your strategy

Open config.yaml in your editor. The starter file is heavily commented — every key has a one-line explanation. Here's the minimal Free-tier setup for OKX, weekly AED 500 with a buy-the-dip overlay:

license:
  tier: free

strategy:
  amount_aed: 500           # AED per buy
  frequency: weekly
  day_of_week: monday
  time: "09:00"
  timezone: "Asia/Dubai"

overlays:
  buy_the_dip:
    enabled: true
    threshold_pct: -10      # if BTC -10% over lookback
    lookback_days: 7
    multiplier: 2.0         # 2× the base AED amount

execution:
  mode: taker               # taker = market order; "maker_only" saves fees but may not fill

routing:
  mode: best_price
  preferred_exchange: null

exchanges:
  okx:
    enabled: true
    api_key_env: OKX_API_KEY
    api_secret_env: OKX_API_SECRET
    passphrase_env: OKX_API_PASSPHRASE
  binance:
    enabled: false
  bitoasis:
    enabled: false

risk:
  max_daily_aed: 1000       # hard daily cap — clamps even big dip-triggered buys
  max_single_buy_aed: 2000  # per-buy cap
  max_consecutive_failures: 5

dry_run: true               # KEEP THIS ON FOR NOW

Now write your API key into an environment file (Docker reads this):

cat > .env <<'EOF'
OKX_API_KEY=your_key_here
OKX_API_SECRET=your_secret_here
OKX_API_PASSPHRASE=your_passphrase_here
EOF
chmod 600 .env
Don't commit .env or config.yaml to git.The repo's .gitignore already excludes them. If you keep your bot in a private repo, double-check.

4. Validate + dry-run

Build the Docker image and validate the config:

docker build -t bitcoiners-dca .
docker run --rm --env-file .env \
  -v $PWD/config.yaml:/app/config.yaml \
  bitcoiners-dca validate

validate parses the YAML, checks license-tier feature gating, confirms your API credentials work, and prints a summary of what the bot will do. If anything is wrong, fix it here before you go any further.

Now run one dry-run buy cycle:

docker run --rm --env-file .env \
  -v $PWD/config.yaml:/app/config.yaml \
  -v $PWD/data:/app/data \
  bitcoiners-dca buy-once

With dry_run: true this prints what it would have bought (exchange, AED amount, BTC estimate, fee, effective price) without placing an order. Read it carefully. If the math looks right, you're ready to go live.

5. Go live

Edit config.yaml and set:

dry_run: false

Then start the bot as a long-running container:

docker compose up -d

The bundled docker-compose.yml runs the bot daemon-mode (cron + interval scheduler) with restart-on-failure policy. Logs go to stdout, which Docker captures. View them with:

docker compose logs -f

Your first real buy will hit at the next scheduled cycle (Monday 09:00 Asia/Dubai in our example). Watch the first one closely.

6. Auto-withdraw to your hardware wallet

This is the part that makes the bot meaningfully different from just clicking "recurring buy" on the exchange. Accumulated BTC gets swept to your own wallet on a schedule, so the exchange never holds material balance.

On your hardware wallet, generate a fresh receive address. Examples:

Verify the address on the hardware device itself (not just in software). Then add it to config.yaml:

auto_withdraw:
  enabled: true
  destination_address: "bc1q...your_hardware_wallet_address..."
  threshold_btc: 0.01       # withdraw whenever exchange balance ≥ 0.01 BTC

For this step you need a withdraw-scope API key on the exchange. The simplest pattern: keep two keys.

Why hardcode the address in config.yaml? The bot intentionally has no UI input for the destination address. If someone compromises the running container, they can't redirect funds — they'd need write access to your config file on disk. Belt and braces.

Restart the bot to pick up the new config:

docker compose restart

7. (Optional) Lightning withdrawals

Pro tier only. If you upgrade later, the bot can withdraw via Lightning on OKX (the only UAE-licensed exchange with native Lightning support at the time of writing). You paste a BOLT11 invoice from your Lightning wallet (Phoenix, Wallet of Satoshi, Aqua) into the CLI and the bot routes payment:

bitcoiners-dca withdraw lnbc1pn... 0.005

Free tier withdraws on-chain only, which is fine for accumulating BTC into long-term cold storage. Lightning matters more if you actually spend sats day-to-day.

8. Monitoring + logs

The bot exposes three things you should watch:

Logs:

docker compose logs -f       # live tail
docker compose logs --tail 100  # last 100 lines

Status snapshot:

docker compose exec dca bitcoiners-dca status

Status shows: license tier, last cycle outcome, lifetime AED spent, lifetime BTC bought, current exchange balances, whether circuit breakers have tripped.

Telegram alerts (recommended):

Create a Telegram bot via @BotFather, get the token, and note your Telegram chat ID (DM @userinfobot). Then:

# in .env
TG_BOT_TOKEN=123456:abcdef...

# in config.yaml
notifications:
  telegram:
    enabled: true
    bot_token_env: TG_BOT_TOKEN
    chat_id: 1031335295   # YOUR chat ID, not Ben's

You'll get a Telegram message after every cycle (buy succeeded, buy failed, withdrawal triggered, circuit breaker tripped).

Tax CSV export:

docker compose exec dca bitcoiners-dca tax-export --year 2026

Writes a UAE-format CSV to ./reports/ with date, exchange, pair, AED, BTC, fee. The format is what an accountant or auditor would want; FTA hasn't published a crypto-specific template yet but this covers all the fields they'll care about.

9. Upgrade to Pro (or stay on Free)

The Free tier is genuinely useful — for a single-exchange AED 500/week DCA with hardware-wallet auto-withdraw it's probably all you need. Don't upgrade because the marketing page lists more features; upgrade if you specifically want one of them.

Things you only get on Pro:

When the closed beta opens you'll receive a Pro license token (a single base64 string). Paste it into config.yaml:

license:
  tier: pro
  key: "eyJ0aWVyIjoicHJvIi..."   # the token from your email

Restart the bot. bitcoiners-dca license now shows your tier as Pro and the previously-gated features are live. License verification is offline (Ed25519-signed token), so the bot doesn't phone home.

Troubleshooting

"OKX request signature invalid"

Almost always a wrong passphrase. The passphrase is case-sensitive and is the one you set when creating the API key on OKX, not your account password. Recreate the key if you've lost it.

BitOasis "401 Unauthorized"

Bearer token issues: confirm the token is in .env as BITOASIS_API_TOKEN, no quotes, no trailing whitespace, no newline at the end. The token format is a long alphanumeric string with hyphens — not a UUID.

Bot says "dry-run mode — no order placed" and I want it to be live

Edit config.yaml: dry_run: false at the bottom of the file. Then docker compose restart.

Circuit breaker tripped — bot won't buy

After 5 consecutive cycle failures the bot auto-pauses (a safety measure against blowing through your daily cap while an exchange is having an outage). Inspect logs to find the root cause, then resume:

docker compose exec dca bitcoiners-dca risk resume

How do I update to a newer version?

cd bitcoiners-dca
git pull
docker compose build --no-cache
docker compose up -d

Your config.yaml, .env, SQLite DB in data/, and tax reports in reports/ are all volume-mounted — they survive image rebuilds.

Where to get help

Email support@bitcoiners.ae with the output of docker compose logs --tail 100 and a short description of what you tried. Once the open-source mirror lands on GitHub, a public issue tracker takes over for Free-tier support; Pro tier gets 24-hour email response either way.

The full Bitcoin community is on @bitcoinersae on Telegram — drop questions there too. UAE Bitcoiners help each other.

Don't want to operate it yourself?

The hosted version is AED 49/month.

Multi-exchange smart routing, advanced overlays, Lightning, and a browser dashboard — we run the bot for you on managed infrastructure.

See features + pricing →