feat: lamassu initial dockerize approach

feat: improve dockerization

feat: finished initial versions of dockerfiles

fix: small fixes to image building
This commit is contained in:
Sérgio Salgado 2022-03-17 16:04:34 +00:00
parent b0860cdea5
commit bd82285ecf
14 changed files with 484 additions and 20 deletions

View file

@ -0,0 +1,72 @@
FROM ubuntu:20.04 as base
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Lisbon
RUN apt-get update
RUN apt-get install -y -q curl \
sudo \
git \
python2-minimal \
build-essential \
libpq-dev \
net-tools
RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
RUN apt-get install nodejs -y -q
FROM base as build-l-a-s
WORKDIR /app
COPY bin/ packages/lamassu-admin-server/bin
COPY lib/ packages/lamassu-admin-server/lib
COPY data/ packages/lamassu-admin-server/data
COPY tools/ packages/lamassu-admin-server/tools
COPY package.json packages/lamassu-admin-server/package.json
COPY Lamassu_CA.pem packages/lamassu-admin-server/Lamassu_CA.pem
WORKDIR /app/packages/lamassu-admin-server
RUN npm install
FROM node:14 as build-admin
WORKDIR /app
COPY new-lamassu-admin/ packages/lamassu-admin
WORKDIR /app/packages/lamassu-admin
RUN npm install
RUN npm run build
FROM ubuntu:20.04 as production-l-a-s
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Lisbon
RUN apt-get update
RUN apt-get install -y -q curl \
sudo \
git \
python2-minimal \
build-essential \
libpq-dev \
net-tools
RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
RUN apt-get install nodejs -y -q
COPY --from=build-l-a-s /app/packages/lamassu-admin-server /app/packages/lamassu-admin-server
COPY --from=build-admin /app/packages/lamassu-admin/build /app/packages/lamassu-admin-server/public
WORKDIR /app/packages/lamassu-admin-server
EXPOSE 443
ENTRYPOINT [ "node" ]
CMD [ "bin/lamassu-admin-server" ]

View file

@ -0,0 +1,32 @@
FROM node:14 as build-admin
WORKDIR /app
# COPY new-lamassu-admin/src packages/lamassu-admin/src
# COPY new-lamassu-admin/patches packages/lamassu-admin/patches
# COPY new-lamassu-admin/public packages/lamassu-admin/public
# COPY new-lamassu-admin/nginx packages/lamassu-admin/nginx
# COPY new-lamassu-admin/.env packages/lamassu-admin/.env
# COPY new-lamassu-admin/.eslintrc.js packages/lamassu-admin/.eslintrc.js
# COPY new-lamassu-admin/jsconfig.json packages/lamassu-admin/jsconfig.json
# COPY new-lamassu-admin/package.json packages/lamassu-admin/package.json
COPY new-lamassu-admin packages/lamassu-admin
WORKDIR /app/packages/lamassu-admin
# RUN npm install
RUN npm run build
FROM nginx:1.21.4-alpine as production-admin
ENV NODE_ENV=production
COPY --from=build-admin /app/packages/lamassu-admin/build /usr/share/nginx/html/
RUN rm /etc/nginx/conf.d/default.conf
COPY --from=build-admin /app/packages/lamassu-admin/nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD [ "nginx", "-g", "daemon off;" ]

View file

@ -0,0 +1,61 @@
FROM ubuntu:20.04 as base
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Lisbon
RUN apt-get update
RUN apt-get install -y -q curl \
sudo \
git \
python2-minimal \
build-essential \
libpq-dev \
net-tools
RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
RUN apt-get install nodejs -y -q
FROM base as build-l-s
WORKDIR /app
COPY bin/ packages/lamassu-server/bin
COPY lib/ packages/lamassu-server/lib
COPY tools/ packages/lamassu-server/tools
COPY migrations/ packages/lamassu-server/migrations
COPY package.json packages/lamassu-server/package.json
COPY Lamassu_CA.pem packages/lamassu-server/Lamassu_CA.pem
WORKDIR /app/packages/lamassu-server
RUN chmod +x tools/build-docker-certs.sh
RUN chmod +x bin/lamassu-server-entrypoint.sh
RUN npm install
FROM ubuntu:20.04 as production-l-s
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Lisbon
RUN apt-get update
RUN apt-get install -y -q curl \
sudo \
git \
python2-minimal \
build-essential \
libpq-dev \
net-tools
RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
RUN apt-get install nodejs -y -q
COPY --from=build-l-s /app/packages/lamassu-server /app/packages/lamassu-server
WORKDIR /app/packages/lamassu-server
EXPOSE 3000
ENTRYPOINT [ "/app/packages/lamassu-server/bin/lamassu-server-entrypoint.sh" ]

View file

@ -1,6 +1,4 @@
#!/usr/bin/env node #!/usr/bin/env node
const FileStore = require('migrate/lib/file-store')
const _ = require('lodash/fp') const _ = require('lodash/fp')
const path = require('path') const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') }) require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
@ -9,8 +7,6 @@ const db = require('../lib/db')
const migrate = require('../lib/migrate') const migrate = require('../lib/migrate')
const { asyncLocalStorage, defaultStore } = require('../lib/async-storage') const { asyncLocalStorage, defaultStore } = require('../lib/async-storage')
const MIGRATE_STATE_PATH = process.env.MIGRATE_STATE_PATH
const createMigration = `CREATE TABLE IF NOT EXISTS migrations ( const createMigration = `CREATE TABLE IF NOT EXISTS migrations (
id serial PRIMARY KEY, id serial PRIMARY KEY,
data json NOT NULL data json NOT NULL
@ -18,14 +14,7 @@ const createMigration = `CREATE TABLE IF NOT EXISTS migrations (
const select = 'select * from migrations limit 1' const select = 'select * from migrations limit 1'
const getMigrateFile = () => { const getMigrateFile = () => Promise.resolve()
return new Promise((resolve, reject) => {
new FileStore(MIGRATE_STATE_PATH).load((err, store) => {
if (err) return reject(err)
return resolve(store)
})
})
}
const store = defaultStore() const store = defaultStore()
asyncLocalStorage.run(store, () => { asyncLocalStorage.run(store, () => {

View file

@ -8,7 +8,7 @@ const authErrors = require('../lib/new-admin/graphql/errors/authentication')
const name = process.argv[2] const name = process.argv[2]
const role = process.argv[3] const role = process.argv[3]
const domain = process.env.HOSTNAME const domain = process.env.LAMASSU_ADMIN_SERVER_IP || process.env.HOSTNAME
if (!domain) { if (!domain) {
console.error('No hostname configured in the environment') console.error('No hostname configured in the environment')
@ -35,7 +35,7 @@ if (role !== 'user' && role !== 'superuser') {
asyncLocalStorage.run(defaultStore(), () => { asyncLocalStorage.run(defaultStore(), () => {
userManagement.createRegisterToken(name, role).then(token => { userManagement.createRegisterToken(name, role).then(token => {
if (domain === 'localhost') { if (domain === 'localhost' && process.env.NODE_ENV !== 'production') {
console.log(`https://${domain}:3001/register?t=${token.token}`) console.log(`https://${domain}:3001/register?t=${token.token}`)
} else { } else {
console.log(`https://${domain}/register?t=${token.token}`) console.log(`https://${domain}/register?t=${token.token}`)

View file

@ -0,0 +1,27 @@
#!/usr/bin/env bash
FILE_1=/etc/ssl/certs/Lamassu_CA.pem
FILE_2=/etc/ssl/certs/Lamassu_OP.pem
FILE_3=/etc/ssl/certs/Lamassu_OP_Root_CA.pem
FILE_4=/etc/ssl/certs/Lamassu_OP_Root_CA.srl
FILE_5=/etc/ssl/private/Lamassu_OP.key
FILE_6=/etc/ssl/private/Lamassu_OP_Root_CA.key
echo "Executing migrations..."
node /app/packages/lamassu-server/bin/lamassu-migrate
echo "Checking for the existence of certificates..."
if [[ ! -f "$FILE_1" || ! -f "$FILE_2" || ! -f "$FILE_3" || ! -f "$FILE_4" || ! -f "$FILE_5" || ! -f "$FILE_6" ]]; then
echo "No Lamassu certificates found. Building them..."
bash /app/packages/lamassu-server/tools/build-docker-certs.sh
fi
USER_COUNT=$(node /app/packages/lamassu-server/tools/check-user-count.js)
if [[ $USER_COUNT == '0' ]]; then
echo "No initial user found. Creating master@lamassu.is..."
node /app/packages/lamassu-server/bin/lamassu-register master@lamassu.is superuser
fi
echo "Starting server..."
node /app/packages/lamassu-server/bin/lamassu-server

143
docker-compose.yaml Normal file
View file

@ -0,0 +1,143 @@
version: "3.8"
networks:
lamassu-network:
ipam:
driver: default
config:
- subnet: "172.29.0.0/24"
services:
database:
container_name: postgres-db
image: postgres
restart: on-failure
environment:
- POSTGRES_DB=lamassu
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres123
logging:
options:
max-size: 10m
max-file: "3"
ports:
- 15432:5432
volumes:
- ~/lamassu-data/psql:/var/lib/postgresql/data
networks:
- lamassu-network
healthcheck:
test: pg_isready -U postgres -d postgres
interval: 3s
timeout: 3s
retries: 10
lamassu-server:
container_name: lamassu-server
build:
context: .
dockerfile: Dockerfiles/server.Dockerfile
target: production-l-s
restart: on-failure
ports:
- 3000:3000
volumes:
- ~/lamassu-data/certs:/etc/ssl/certs
- ~/lamassu-data/private:/etc/ssl/private
- ~/lamassu-data/files:/opt/lamassu-server
- ~/lamassu-data/mnemonics:/etc/lamassu/mnemonics
- ~/lamassu-data/ofac:/var/lamassu/ofac
- ~/lamassu-data/.migrate:/etc/lamassu/.migrate
- ~/lamassu-data/blockchains:/mnt/blockchains
networks:
lamassu-network:
ipv4_address: 172.29.0.3
environment:
- NODE_ENV=production
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres123
- POSTGRES_HOST=postgres-db
- POSTGRES_PORT=5432
- POSTGRES_DB=lamassu
- LAMASSU_CA_PATH=/etc/ssl/certs/Lamassu_CA.pem
- CA_PATH=/etc/ssl/certs/Lamassu_OP_Root_CA.pem
- CERT_PATH=/etc/ssl/certs/Lamassu_OP.pem
- KEY_PATH=/etc/ssl/private/Lamassu_OP.key
- MNEMONIC_PATH=/etc/lamassu/mnemonics/mnemonic.txt
- MIGRATE_STATE_PATH=/etc/lamassu/.migrate
- BLOCKCHAIN_DIR=/mnt/blockchains
- OFAC_DATA_DIR=/var/lamassu/ofac
- ID_PHOTO_CARD_DIR=/opt/lamassu-server/idphotocard
- FRONT_CAMERA_DIR=/opt/lamassu-server/frontcamera
- OPERATOR_DATA_DIR=/opt/lamassu-server/operatordata
- STRIKE_BASE_URL=https://api.strike.acinq.co/api/
- COIN_ATM_RADAR_URL=https://coinatmradar.info/api/lamassu/
- OFAC_SOURCES_NAMES=sdn_advanced,cons_advanced
- OFAC_SOURCES_URLS=https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml,https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml
- HOSTNAME=localhost
- LOG_LEVEL=info
depends_on:
database:
condition: service_healthy
lamassu-admin-server:
container_name: lamassu-admin-server
build:
context: .
dockerfile: Dockerfiles/admin-server.Dockerfile
target: production-l-a-s
restart: on-failure
ports:
- 443:443
volumes:
- ~/lamassu-data/certs:/etc/ssl/certs
- ~/lamassu-data/private:/etc/ssl/private
- ~/lamassu-data/files:/opt/lamassu-server
- ~/lamassu-data/mnemonics:/etc/lamassu/mnemonics
- ~/lamassu-data/ofac:/var/lamassu/ofac
- ~/lamassu-data/.migrate:/etc/lamassu/.migrate
- ~/lamassu-data/blockchains:/mnt/blockchains
networks:
- lamassu-network
environment:
- NODE_ENV=production
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres123
- POSTGRES_HOST=postgres-db
- POSTGRES_PORT=5432
- POSTGRES_DB=lamassu
- LAMASSU_CA_PATH=/etc/ssl/certs/Lamassu_CA.pem
- CA_PATH=/etc/ssl/certs/Lamassu_OP_Root_CA.pem
- CERT_PATH=/etc/ssl/certs/Lamassu_OP.pem
- KEY_PATH=/etc/ssl/private/Lamassu_OP.key
- MNEMONIC_PATH=/etc/lamassu/mnemonics/mnemonic.txt
- MIGRATE_STATE_PATH=/etc/lamassu/.migrate
- BLOCKCHAIN_DIR=/mnt/blockchains
- OFAC_DATA_DIR=/var/lamassu/ofac
- ID_PHOTO_CARD_DIR=/opt/lamassu-server/idphotocard
- FRONT_CAMERA_DIR=/opt/lamassu-server/frontcamera
- OPERATOR_DATA_DIR=/opt/lamassu-server/operatordata
- STRIKE_BASE_URL=https://api.strike.acinq.co/api/
- COIN_ATM_RADAR_URL=https://coinatmradar.info/api/lamassu/
- OFAC_SOURCES_NAMES=sdn_advanced,cons_advanced
- OFAC_SOURCES_URLS=https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml,https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml
- HOSTNAME=172.29.0.3
- LOG_LEVEL=info
depends_on:
lamassu-server:
condition: service_started
# admin:
# container_name: lamassu-admin
# build:
# context: .
# dockerfile: Dockerfiles/admin.Dockerfile
# target: production-admin
# restart: always
# ports:
# - 80:80
# networks:
# - lamassu-network
# depends_on:
# lamassu-admin-server:
# condition: service_started

View file

@ -15,8 +15,8 @@ DbMigrateStore.prototype.save = function (set, fn) {
} }
DbMigrateStore.prototype.load = function (fn) { DbMigrateStore.prototype.load = function (fn) {
db.one('select data from migrations').then(({ data }) => { db.oneOrNone('select data from migrations').then(res => {
fn(null, data) fn(null, res?.data || {})
}) })
} }

View file

@ -2,4 +2,4 @@ SKIP_PREFLIGHT_CHECK=true
HTTPS=true HTTPS=true
REACT_APP_TYPE_CHECK_SANCTUARY=false REACT_APP_TYPE_CHECK_SANCTUARY=false
PORT=3001 PORT=3001
REACT_APP_BUILD_TARGET=PAZUZ REACT_APP_BUILD_TARGET=LAMASSU

View file

@ -0,0 +1,28 @@
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
location /graphql {
proxy_pass https://lamassu-admin-server/graphql;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

13
package-lock.json generated
View file

@ -9184,9 +9184,9 @@
} }
}, },
"dotenv": { "dotenv": {
"version": "6.2.0", "version": "16.0.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz",
"integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==" "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q=="
}, },
"drbg.js": { "drbg.js": {
"version": "1.0.1", "version": "1.0.1",
@ -15403,6 +15403,13 @@
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"slug": "^0.9.2" "slug": "^0.9.2"
},
"dependencies": {
"dotenv": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz",
"integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w=="
}
} }
}, },
"miller-rabin": { "miller-rabin": {

View file

@ -28,6 +28,7 @@
"dataloader": "^2.0.0", "dataloader": "^2.0.0",
"date-fns": "^2.26.0", "date-fns": "^2.26.0",
"date-fns-tz": "^1.1.6", "date-fns-tz": "^1.1.6",
"dotenv": "^16.0.0",
"ethereumjs-tx": "^1.3.3", "ethereumjs-tx": "^1.3.3",
"ethereumjs-util": "^5.2.0", "ethereumjs-util": "^5.2.0",
"ethereumjs-wallet": "^0.6.3", "ethereumjs-wallet": "^0.6.3",

View file

@ -0,0 +1,89 @@
#!/usr/bin/env bash
set -e
export LOG_FILE=/tmp/install.log
CERT_DIR=/etc/ssl/certs
KEY_DIR=/etc/ssl/private
CONFIG_DIR=/etc/lamassu
MIGRATE_STATE_PATH=$CONFIG_DIR/.migrate
LAMASSU_CA_PATH=$CERT_DIR/Lamassu_CA.pem
CA_KEY_PATH=$KEY_DIR/Lamassu_OP_Root_CA.key
CA_PATH=$CERT_DIR/Lamassu_OP_Root_CA.pem
SERVER_KEY_PATH=$KEY_DIR/Lamassu_OP.key
SERVER_CERT_PATH=$CERT_DIR/Lamassu_OP.pem
MNEMONIC_DIR=$CONFIG_DIR/mnemonics
MNEMONIC_FILE=$MNEMONIC_DIR/mnemonic.txt
BACKUP_DIR=/var/backups/postgresql
BLOCKCHAIN_DIR=/mnt/blockchains
OFAC_DATA_DIR=/var/lamassu/ofac
ID_PHOTO_CARD_DIR=/opt/lamassu-server/idphotocard
FRONTCAMERA_DIR=/opt/lamassu-server/frontcamera
OPERATOR_DIR=/opt/lamassu-server/operatordata
decho () {
echo `date +"%H:%M:%S"` $1
}
IP=$(hostname -i)
NODE_MODULES=$(npm -g root)
NPM_BIN=$(npm -g bin)
decho "Generating mnemonic..."
mkdir -p $MNEMONIC_DIR
SEED=$(openssl rand -hex 32)
MNEMONIC=$(/app/packages/lamassu-server/bin/bip39 $SEED)
echo "$MNEMONIC" > $MNEMONIC_FILE
mkdir -p $CERT_DIR
mkdir -p $CONFIG_DIR
decho "Generating SSL certificates..."
sed -i '/RANDFILE/d' /etc/ssl/openssl.cnf
openssl genrsa \
-out $CA_KEY_PATH \
4096
openssl req \
-x509 \
-sha256 \
-new \
-nodes \
-key $CA_KEY_PATH \
-days 3650 \
-out $CA_PATH \
-subj "/C=IS/ST=/L=Reykjavik/O=Lamassu Operator CA/CN=operator.lamassu.is"
openssl genrsa \
-out $SERVER_KEY_PATH \
4096
openssl req -new \
-key $SERVER_KEY_PATH \
-out /tmp/Lamassu_OP.csr.pem \
-subj "/C=IS/ST=/L=Reykjavik/O=Lamassu Operator/CN=$IP" \
-reqexts SAN \
-sha256 \
-config <(cat /etc/ssl/openssl.cnf \
<(printf "[SAN]\nsubjectAltName=IP.1:$IP"))
openssl x509 \
-req -in /tmp/Lamassu_OP.csr.pem \
-CA $CA_PATH \
-CAkey $CA_KEY_PATH \
-CAcreateserial \
-out $SERVER_CERT_PATH \
-extfile <(cat /etc/ssl/openssl.cnf \
<(printf "[SAN]\nsubjectAltName=IP.1:$IP")) \
-extensions SAN \
-days 3650
rm /tmp/Lamassu_OP.csr.pem
decho "Copying Lamassu certificate authority..."
LAMASSU_CA_FILE=/app/packages/lamassu-server/Lamassu_CA.pem
cp $LAMASSU_CA_FILE $LAMASSU_CA_PATH
mkdir -p $OFAC_DATA_DIR

15
tools/check-user-count.js Normal file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env node
const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
const db = require('../lib/db')
const getCount = () => {
return db.one(`SELECT COUNT(*) FROM users`)
.then(res => {
process.stdout.write(res.count)
process.exit(0)
})
}
getCount()