#!/bin/bash set -euo pipefail if [ "$(id -u)" -ne 0 ]; then echo "Run as root" exit 1 fi apt update apt upgrade -y apt install -y nginx tor python3 python3-venv python3-pip qrencode sqlite3 git curl socat # create site user useradd -m -s /bin/bash horus || true mkdir -p /home/horus/www chown -R horus:horus /home/horus # nginx config (listen on localhost only) cat > /etc/nginx/sites-available/horus <<'NGINX' server { listen 127.0.0.1:8080; server_name localhost; root /home/horus/www; index index.html; access_log off; error_log /dev/null; } NGINX ln -sf /etc/nginx/sites-available/horus /etc/nginx/sites-enabled/horus nginx -t systemctl restart nginx # tor hidden service for site if ! grep -q "HiddenServiceDir /var/lib/tor/horus_hidden/" /etc/tor/torrc 2>/dev/null; then cat >> /etc/tor/torrc <<'TOR' HiddenServiceDir /var/lib/tor/horus_hidden/ HiddenServiceVersion 3 HiddenServicePort 80 127.0.0.1:8080 TOR fi systemctl restart tor || true # prepare python env and flask app as horus user sudo -u horus bash -lc "python3 -m venv /home/horus/venv && /home/horus/venv/bin/pip install --upgrade pip flask requests" # create minimal flask app cat > /home/horus/www/app.py <<'PY' from flask import Flask, render_template_string, send_from_directory import sqlite3, os, subprocess, requests app = Flask(__name__) DB='/home/horus/site.db' SITE_ROOT='/home/horus/www' RPC_URL='http://127.0.0.1:18082/json_rpc' # monero-wallet-rpc INDEX_HTML='''

Horus Shop

''' BUY_HTML='''

{{name}}

Price: {{price}} XMR

Address: {{addr}}

Status: {{status}}

''' def init_db(): if not os.path.exists(DB): conn=sqlite3.connect(DB); c=conn.cursor() c.execute('CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price REAL)') c.execute('CREATE TABLE orders (id INTEGER PRIMARY KEY, product_id INTEGER, subaddress TEXT, amount REAL, status TEXT)') conn.commit(); conn.close() def rpc(method, params=None): payload={'jsonrpc':'2.0','id':'0','method':method} if params: payload['params']=params r=requests.post(RPC_URL, json=payload, timeout=10) return r.json() @app.route('/') def index(): conn=sqlite3.connect(DB); c=conn.cursor() c.execute('SELECT id,name,price FROM products'); products=c.fetchall(); conn.close() return render_template_string(INDEX_HTML, products=products) @app.route('/buy/') def buy(pid): conn=sqlite3.connect(DB); c=conn.cursor() c.execute('SELECT name,price FROM products WHERE id=?', (pid,)); row=c.fetchone() if not row: return "Not found",404 name, price = row res = rpc('create_address', {'account_index':0}) addr = res.get('result',{}).get('address','') c.execute('INSERT INTO orders (product_id, subaddress, amount, status) VALUES (?,?,?,?)', (pid, addr, price, 'pending')) oid = c.lastrowid; conn.commit(); conn.close() subprocess.run(['qrencode','-o', f'/home/horus/www/{oid}.png', addr]) return render_template_string(BUY_HTML, name=name, price=price, addr=addr, order_id=oid, status='pending') @app.route('/qr/') def qr(fn): return send_from_directory('/home/horus/www', fn) if __name__=='__main__': init_db() app.run(host='127.0.0.1', port=5000) PY chown -R horus:horus /home/horus/www chmod 750 /home/horus/www/app.py # systemd for flask app (run as horus) cat > /etc/systemd/system/horus.service <<'UNIT' [Unit] Description=Horus Flask App After=network.target [Service] User=horus WorkingDirectory=/home/horus/www Environment=PATH=/home/horus/venv/bin ExecStart=/home/horus/venv/bin/python /home/horus/www/app.py Restart=on-failure [Install] WantedBy=multi-user.target UNIT systemctl daemon-reload systemctl enable --now horus.service # forward 127.0.0.1:8080 -> 127.0.0.1:5000 via socat systemd cat > /etc/systemd/system/horus-socat.service <<'SOC' [Unit] Description=Forward 127.0.0.1:8080 to 127.0.0.1:5000 After=network.target [Service] ExecStart=/usr/bin/socat TCP-LISTEN:8080,bind=127.0.0.1,fork TCP:127.0.0.1:5000 Restart=on-failure [Install] WantedBy=multi-user.target SOC systemctl enable --now horus-socat.service chown -R horus:horus /home/horus echo "HORUS INSTALL DONE" sleep 2 if [ -f /var/lib/tor/horus_hidden/hostname ]; then cat /var/lib/tor/horus_hidden/hostname else sleep 2 cat /var/lib/tor/horus_hidden/hostname || true fi