move monero wallet creation into container entrypoint
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# NullCart
|
# NullCart
|
||||||
|
|
||||||
Self-hosted Monero shop with clearnet (HTTPS) and Tor onion hosting.
|
Self-hosted crypto shop with clearnet (HTTPS) and Tor onion hosting.
|
||||||
|
|
||||||
For production deployment, see the [deployment guide](deploy/DEPLOYMENT_GUIDE.md).
|
For production deployment, see the [deployment guide](deploy/DEPLOYMENT_GUIDE.md).
|
||||||
|
|
||||||
@@ -12,9 +12,6 @@ For production deployment, see the [deployment guide](deploy/DEPLOYMENT_GUIDE.md
|
|||||||
# Create and edit .env.dev as needed
|
# Create and edit .env.dev as needed
|
||||||
cp .env.example .env.dev
|
cp .env.example .env.dev
|
||||||
|
|
||||||
# Create monero wallet used by shop
|
|
||||||
./monero-wallet-rpc/setup-monero-wallet.sh --env-file .env.dev
|
|
||||||
|
|
||||||
# Build and start docker containers
|
# Build and start docker containers
|
||||||
docker compose --env-file .env.dev -f docker-compose.dev.yml build --no-cache
|
docker compose --env-file .env.dev -f docker-compose.dev.yml build --no-cache
|
||||||
docker compose --env-file .env.dev -f docker-compose.dev.yml up --force-recreate
|
docker compose --env-file .env.dev -f docker-compose.dev.yml up --force-recreate
|
||||||
|
|||||||
@@ -74,13 +74,7 @@ Example (default in `.env.example`):
|
|||||||
|
|
||||||
Orders up to 30 → 0 confirmations; up to 100 → 3; up to 300 → 5; above 300 → 10. Tiers are shown read-only in CMS shop settings.
|
Orders up to 30 → 0 confirmations; up to 100 → 3; up to 300 → 5; above 300 → 10. Tiers are shown read-only in CMS shop settings.
|
||||||
|
|
||||||
## 5. Create the Monero wallet
|
## 5. Bootstrap TLS certificates
|
||||||
|
|
||||||
```bash
|
|
||||||
./monero-wallet-rpc/setup-monero-wallet.sh --env-file .env.prod
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6. Bootstrap TLS certificates
|
|
||||||
|
|
||||||
Nginx needs certificate files before it can start on port 443. For the **first** deploy, create a temporary self-signed pair (replaced after Let's Encrypt):
|
Nginx needs certificate files before it can start on port 443. For the **first** deploy, create a temporary self-signed pair (replaced after Let's Encrypt):
|
||||||
|
|
||||||
@@ -88,9 +82,9 @@ Nginx needs certificate files before it can start on port 443. For the **first**
|
|||||||
./deploy/scripts/bootstrap-certs.sh
|
./deploy/scripts/bootstrap-certs.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
After the stack is running, obtain real certificates (step 8).
|
After the stack is running, obtain real certificates (step 7).
|
||||||
|
|
||||||
## 7. Start the stack
|
## 6. Start the stack
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/scripts/deploy.sh
|
./deploy/scripts/deploy.sh
|
||||||
@@ -102,7 +96,7 @@ Wait until `backend` and `nginx` are healthy:
|
|||||||
docker compose --env-file .env.prod -f docker-compose.prod.yml ps
|
docker compose --env-file .env.prod -f docker-compose.prod.yml ps
|
||||||
```
|
```
|
||||||
|
|
||||||
## 8. Issue Let's Encrypt certificates
|
## 7. Issue Let's Encrypt certificates
|
||||||
|
|
||||||
Remove the temporary bootstrap certificates under `deploy/certs/live/` (Certbot cannot issue into the layout created by `bootstrap-certs.sh`):
|
Remove the temporary bootstrap certificates under `deploy/certs/live/` (Certbot cannot issue into the layout created by `bootstrap-certs.sh`):
|
||||||
|
|
||||||
@@ -142,20 +136,20 @@ Save and exit the editor. Optional — run once manually to verify:
|
|||||||
/root/nullcart/deploy/scripts/renew-certs.sh
|
/root/nullcart/deploy/scripts/renew-certs.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## 9. Tor onion address
|
## 8. Tor onion address
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/scripts/show-onion.sh
|
./deploy/scripts/show-onion.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## 10. Complete shop setup
|
## 9. Complete shop setup
|
||||||
|
|
||||||
1. Open the CMS on clearnet or onion (`/cms`).
|
1. Open the CMS on clearnet or onion (`/cms`).
|
||||||
2. Log in with `CMS_PASSWORD` from `.env.prod`.
|
2. Log in with `CMS_PASSWORD` from `.env.prod`.
|
||||||
3. Finish the setup checklist in settings.
|
3. Finish the setup checklist in settings.
|
||||||
4. Connect SimpleX notifications in shop settings.
|
4. Connect SimpleX notifications in shop settings.
|
||||||
|
|
||||||
## 11. Updates
|
## 10. Updates
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/scripts/update.sh
|
./deploy/scripts/update.sh
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ services:
|
|||||||
]
|
]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 10
|
||||||
start_period: 60s
|
start_period: 300s
|
||||||
|
|
||||||
simplex-cli:
|
simplex-cli:
|
||||||
build:
|
build:
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ services:
|
|||||||
]
|
]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 10
|
||||||
start_period: 60s
|
start_period: 300s
|
||||||
|
|
||||||
simplex-cli:
|
simplex-cli:
|
||||||
build:
|
build:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ RUN apt-get update \
|
|||||||
&& curl -fsSL "https://downloads.getmonero.org/cli/monero-linux-${monero_arch}-v${MONERO_VERSION}.tar.bz2" \
|
&& curl -fsSL "https://downloads.getmonero.org/cli/monero-linux-${monero_arch}-v${MONERO_VERSION}.tar.bz2" \
|
||||||
| tar -xj -C /tmp \
|
| tar -xj -C /tmp \
|
||||||
&& install -m 755 "$(find /tmp -type f -name monero-wallet-rpc | head -n 1)" /monero-wallet-rpc \
|
&& install -m 755 "$(find /tmp -type f -name monero-wallet-rpc | head -n 1)" /monero-wallet-rpc \
|
||||||
|
&& install -m 755 "$(find /tmp -type f -name monero-wallet-cli | head -n 1)" /monero-wallet-cli \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
FROM debian:bookworm-slim
|
FROM debian:bookworm-slim
|
||||||
@@ -22,17 +23,10 @@ RUN apt-get update \
|
|||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY --from=build /monero-wallet-rpc /usr/local/bin/monero-wallet-rpc
|
COPY --from=build /monero-wallet-rpc /usr/local/bin/monero-wallet-rpc
|
||||||
|
COPY --from=build /monero-wallet-cli /usr/local/bin/monero-wallet-cli
|
||||||
|
|
||||||
CMD ["/bin/sh", "-ec", "\
|
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||||
exec monero-wallet-rpc \
|
|
||||||
\"--${MONERO_NETWORK}\" \
|
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||||
--daemon-address=\"${MONERO_DAEMON_ADDRESS}\" \
|
|
||||||
--trusted-daemon \
|
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||||
--no-initial-sync \
|
|
||||||
--rpc-bind-ip=0.0.0.0 \
|
|
||||||
--rpc-bind-port=${MONERO_WALLET_RPC_PORT} \
|
|
||||||
--confirm-external-bind \
|
|
||||||
--rpc-login=\"${MONERO_WALLET_RPC_USERNAME}:${MONERO_WALLET_RPC_PASSWORD}\" \
|
|
||||||
--wallet-file=\"/monero/wallet/${MONERO_WALLET_NAME}\" \
|
|
||||||
--password=\"${MONERO_WALLET_PASSWORD}\" \
|
|
||||||
"]
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
WALLET_DIR="/monero/wallet"
|
||||||
|
WALLET_PATH="${WALLET_DIR}/${MONERO_WALLET_NAME}"
|
||||||
|
NETWORK_FLAG="--${MONERO_NETWORK}"
|
||||||
|
|
||||||
|
mkdir -p "${WALLET_DIR}"
|
||||||
|
chmod 700 "${WALLET_DIR}"
|
||||||
|
|
||||||
|
if [[ ! -f "${WALLET_PATH}" && ! -f "${WALLET_PATH}.keys" ]]; then
|
||||||
|
echo "Creating ${MONERO_NETWORK} wallet at ${WALLET_PATH}..."
|
||||||
|
|
||||||
|
monero-wallet-cli "${NETWORK_FLAG}" \
|
||||||
|
--offline \
|
||||||
|
--log-file /dev/null \
|
||||||
|
--generate-new-wallet "${WALLET_PATH}" \
|
||||||
|
--password "${MONERO_WALLET_PASSWORD}" \
|
||||||
|
--mnemonic-language English \
|
||||||
|
--command save
|
||||||
|
|
||||||
|
chmod 600 "${WALLET_PATH}" "${WALLET_PATH}.keys" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "Wallet created at ${WALLET_PATH}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec monero-wallet-rpc \
|
||||||
|
"${NETWORK_FLAG}" \
|
||||||
|
--daemon-address="${MONERO_DAEMON_ADDRESS}" \
|
||||||
|
--trusted-daemon \
|
||||||
|
--no-initial-sync \
|
||||||
|
--rpc-bind-ip=0.0.0.0 \
|
||||||
|
--rpc-bind-port="${MONERO_WALLET_RPC_PORT}" \
|
||||||
|
--confirm-external-bind \
|
||||||
|
--rpc-login="${MONERO_WALLET_RPC_USERNAME}:${MONERO_WALLET_RPC_PASSWORD}" \
|
||||||
|
--wallet-file="${WALLET_PATH}" \
|
||||||
|
--password="${MONERO_WALLET_PASSWORD}"
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
||||||
ENV_FILE=""
|
|
||||||
MONERO_CLI_INSTALL_PATH="/usr/local/bin/monero-wallet-cli"
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<EOF
|
|
||||||
Usage: $(basename "$0") --env-file PATH
|
|
||||||
|
|
||||||
Installs official monero-wallet-cli system-wide (if missing) and creates the shop wallet
|
|
||||||
in monero-wallet-rpc/wallet on the host. monero-wallet-rpc mounts the same directory via compose.
|
|
||||||
|
|
||||||
Ubuntu/Debian only (uses apt-get for curl, tar, and bzip2 if missing).
|
|
||||||
|
|
||||||
Run after filling in .env (especially MONERO_WALLET_PASSWORD), before docker compose up.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--env-file PATH Env file to load (required)
|
|
||||||
-h, --help Show this help
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--env-file)
|
|
||||||
ENV_FILE="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
-h | --help)
|
|
||||||
usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown option: $1" >&2
|
|
||||||
usage >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z "$ENV_FILE" ]]; then
|
|
||||||
echo "--env-file is required." >&2
|
|
||||||
usage >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$ENV_FILE" != /* ]]; then
|
|
||||||
ENV_FILE="${ROOT_DIR}/${ENV_FILE#./}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -f "$ENV_FILE" ]]; then
|
|
||||||
echo "Env file not found: $ENV_FILE" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -a
|
|
||||||
# shellcheck disable=SC1090
|
|
||||||
source "$ENV_FILE"
|
|
||||||
set +a
|
|
||||||
|
|
||||||
main() {
|
|
||||||
validate_env
|
|
||||||
ensure_dependencies
|
|
||||||
setup_wallet_config
|
|
||||||
create_wallet_if_missing
|
|
||||||
}
|
|
||||||
|
|
||||||
validate_env() {
|
|
||||||
local missing=()
|
|
||||||
|
|
||||||
for var in MONERO_VERSION MONERO_WALLET_DIR MONERO_WALLET_NAME MONERO_NETWORK MONERO_WALLET_PASSWORD; do
|
|
||||||
if [[ -z "${!var:-}" ]]; then
|
|
||||||
missing+=("$var")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
||||||
echo "Missing required env vars in ${ENV_FILE}: ${missing[*]}" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$MONERO_NETWORK" in
|
|
||||||
mainnet | stagenet | testnet) ;;
|
|
||||||
*)
|
|
||||||
echo "MONERO_NETWORK must be mainnet, stagenet, or testnet (got: ${MONERO_NETWORK})." >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_dependencies() {
|
|
||||||
if ! command -v apt-get >/dev/null 2>&1; then
|
|
||||||
echo "apt-get is required. This script supports Ubuntu/Debian only." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local missing=()
|
|
||||||
|
|
||||||
for cmd in curl tar bzip2; do
|
|
||||||
if command -v "$cmd" >/dev/null 2>&1; then
|
|
||||||
log_skip "$cmd"
|
|
||||||
else
|
|
||||||
log_install "$cmd"
|
|
||||||
missing+=("$cmd")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
||||||
run_privileged apt-get update -qq
|
|
||||||
run_privileged apt-get install -y -qq "${missing[@]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
install_monero_wallet_cli_if_missing
|
|
||||||
}
|
|
||||||
|
|
||||||
install_monero_wallet_cli_if_missing() {
|
|
||||||
local arch archive_url tmp_dir extracted_cli
|
|
||||||
|
|
||||||
if command -v monero-wallet-cli >/dev/null 2>&1; then
|
|
||||||
log_skip "monero-wallet-cli"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_install "monero-wallet-cli"
|
|
||||||
|
|
||||||
arch="$(uname -m)"
|
|
||||||
|
|
||||||
case "$arch" in
|
|
||||||
x86_64 | amd64)
|
|
||||||
archive_url="https://downloads.getmonero.org/cli/monero-linux-x64-v${MONERO_VERSION}.tar.bz2"
|
|
||||||
;;
|
|
||||||
aarch64 | arm64)
|
|
||||||
archive_url="https://downloads.getmonero.org/cli/monero-linux-armv8-v${MONERO_VERSION}.tar.bz2"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported CPU architecture: ${arch}" >&2
|
|
||||||
echo "Install monero-wallet-cli from https://www.getmonero.org/downloads/ and re-run." >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
tmp_dir="$(mktemp -d)"
|
|
||||||
trap "rm -rf '${tmp_dir}'" RETURN
|
|
||||||
|
|
||||||
curl -fsSL "$archive_url" | tar -xj -C "$tmp_dir"
|
|
||||||
extracted_cli="$(find "$tmp_dir" -type f -name monero-wallet-cli | head -n 1)"
|
|
||||||
|
|
||||||
if [[ -z "$extracted_cli" ]]; then
|
|
||||||
echo "Could not find monero-wallet-cli in the downloaded archive." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
run_privileged install -m 755 "$extracted_cli" "$MONERO_CLI_INSTALL_PATH"
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_wallet_config() {
|
|
||||||
WALLET_DIR="$(resolve_path "$MONERO_WALLET_DIR")"
|
|
||||||
WALLET_PATH="${WALLET_DIR}/${MONERO_WALLET_NAME}"
|
|
||||||
NETWORK="$MONERO_NETWORK"
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_path() {
|
|
||||||
local path="$1"
|
|
||||||
|
|
||||||
if [[ "$path" != /* ]]; then
|
|
||||||
path="${ROOT_DIR}/${path#./}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf '%s' "$path"
|
|
||||||
}
|
|
||||||
|
|
||||||
create_wallet_if_missing() {
|
|
||||||
mkdir -p "$WALLET_DIR"
|
|
||||||
chmod 700 "$WALLET_DIR"
|
|
||||||
|
|
||||||
if [[ -f "$WALLET_PATH" || -f "${WALLET_PATH}.keys" ]]; then
|
|
||||||
echo "Wallet already exists at ${WALLET_PATH} — skipping creation."
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Creating ${NETWORK} wallet at ${WALLET_PATH}..."
|
|
||||||
|
|
||||||
monero-wallet-cli "--${NETWORK}" \
|
|
||||||
--offline \
|
|
||||||
--log-file /dev/null \
|
|
||||||
--generate-new-wallet "$WALLET_PATH" \
|
|
||||||
--password "$MONERO_WALLET_PASSWORD" \
|
|
||||||
--mnemonic-language English \
|
|
||||||
--command save
|
|
||||||
|
|
||||||
chmod 600 "${WALLET_PATH}" "${WALLET_PATH}.keys" 2>/dev/null || true
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
|
|
||||||
Wallet created.
|
|
||||||
|
|
||||||
Wallet directory: ${WALLET_DIR}
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
run_privileged() {
|
|
||||||
if [[ "${EUID}" -eq 0 ]]; then
|
|
||||||
"$@"
|
|
||||||
elif command -v sudo >/dev/null 2>&1; then
|
|
||||||
sudo "$@"
|
|
||||||
else
|
|
||||||
echo "Root or sudo is required to install missing packages." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
log_skip() {
|
|
||||||
echo "Package ${1} already installed — skipping."
|
|
||||||
}
|
|
||||||
|
|
||||||
log_install() {
|
|
||||||
echo "Package ${1} is not installed — installing..."
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
||||||
Reference in New Issue
Block a user