139 lines
4.9 KiB
Bash
139 lines
4.9 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
mkdir -p logs download_cache app/files
|
|
|
|
echo "BUILD_HASH = \"$(python3 -c 'import uuid, hashlib; print(hashlib.sha256(uuid.uuid4().bytes).hexdigest()[:8])')\"" > app/build_version.py
|
|
|
|
cat <<'EOF'
|
|
__ __ __ __
|
|
/ | / | / | / |
|
|
$$ | $$ | ______ ______ _$$ |_ ______ __ __ $$/
|
|
$$ | $$ |/ \ / \ / $$ | / \ / \ / |/ |
|
|
$$ \ /$$//$$$$$$ |/$$$$$$ |$$$$$$/ /$$$$$$ |$$ \/$$/ $$ |
|
|
$$ /$$/ $$ | $$ |$$ | $$/ $$ | __ $$ $$ | $$ $$< $$ |
|
|
$$ $$/ $$ \__$$ |$$ | $$ |/ |$$$$$$$$/ /$$$$ \ $$ |
|
|
$$$/ $$ $$/ $$ | $$ $$/ $$ |/$$/ $$ |$$ |
|
|
$/ $$$$$$/ $$/ $$$$/ $$$$$$$/ $$/ $$/ $$/
|
|
|
|
|
|
EOF
|
|
|
|
python3 - <<'PYEOF'
|
|
import os
|
|
from app.config import Config
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
from cryptography.hazmat.backends import default_backend
|
|
|
|
def generate_key_if_missing(key_size: int, priv_path: str, pub_path: str):
|
|
if os.path.exists(priv_path):
|
|
return
|
|
parent_dir = os.path.dirname(priv_path)
|
|
if parent_dir:
|
|
os.makedirs(parent_dir, exist_ok=True)
|
|
priv_key = rsa.generate_private_key(
|
|
public_exponent=65537,
|
|
key_size=key_size,
|
|
backend=default_backend()
|
|
)
|
|
with open(priv_path, "wb") as f:
|
|
f.write(
|
|
priv_key.private_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
|
encryption_algorithm=serialization.NoEncryption()
|
|
)
|
|
)
|
|
with open(pub_path, "wb") as f:
|
|
f.write(
|
|
priv_key.public_key().public_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
|
)
|
|
)
|
|
|
|
def generate_ms_blob_if_missing(pub_path: str, blob_path: str):
|
|
if os.path.exists(blob_path) or not os.path.exists(pub_path):
|
|
return
|
|
try:
|
|
import struct, base64
|
|
with open(pub_path, "rb") as f:
|
|
pub_key = serialization.load_pem_public_key(f.read(), backend=default_backend())
|
|
blobheader = struct.pack('<BBHI', 0x06, 0x02, 0, 0x0000a400)
|
|
numbers = pub_key.public_numbers()
|
|
bitlen = pub_key.key_size
|
|
rsapubkey = struct.pack('<4sII', b'RSA1', bitlen, numbers.e)
|
|
n_bytes = numbers.n.to_bytes(bitlen // 8, byteorder='little')
|
|
blob = blobheader + rsapubkey + n_bytes
|
|
b64_blob = base64.b64encode(blob).decode('ascii')
|
|
with open(blob_path, "w") as f:
|
|
f.write(b64_blob)
|
|
except Exception as e:
|
|
print(f"Notice: Failed to generate MS blob for {pub_path}: {e}")
|
|
|
|
generate_key_if_missing(1024, Config.RSA_PRIVATE_KEY_PATH, "./app/files/rsa_public_1024.pub")
|
|
generate_key_if_missing(2048, Config.RSA_PRIVATE_KEY_PATH2, "./app/files/rsa_public_2048.pub")
|
|
generate_key_if_missing(2048, Config.GAMESERVER_COMM_PRIVATE_KEY_LOCATION, "./app/files/rsa_public_gameserver.pub")
|
|
|
|
generate_ms_blob_if_missing("./app/files/rsa_public_1024.pub", "./app/files/2016pub.blob")
|
|
generate_ms_blob_if_missing("./app/files/rsa_public_2048.pub", "./app/files/2018pub.blob")
|
|
PYEOF
|
|
|
|
if command -v openssl >/dev/null 2>&1; then
|
|
openssl rsa -pubin -inform PEM -in ./app/files/rsa_public_1024.pub -outform "MS PUBLICKEYBLOB" 2>/dev/null | base64 > ./app/files/2016pub.blob || true
|
|
openssl rsa -pubin -inform PEM -in ./app/files/rsa_public_2048.pub -outform "MS PUBLICKEYBLOB" 2>/dev/null | base64 > ./app/files/2018pub.blob || true
|
|
fi
|
|
|
|
python3 - <<'PYEOF'
|
|
import time
|
|
import sys
|
|
import redis
|
|
import psycopg2
|
|
from app.config import Config
|
|
|
|
max_retries = 30
|
|
|
|
for i in range(max_retries):
|
|
try:
|
|
r = redis.from_url(Config.FLASK_LIMITED_STORAGE_URI)
|
|
r.ping()
|
|
break
|
|
except Exception as e:
|
|
print(f"Waiting for Redis ({i+1}/{max_retries})...")
|
|
time.sleep(2)
|
|
else:
|
|
print("Redis connection timeout.")
|
|
sys.exit(1)
|
|
|
|
for i in range(max_retries):
|
|
try:
|
|
conn = psycopg2.connect(Config.SQLALCHEMY_DATABASE_URI)
|
|
conn.close()
|
|
break
|
|
except Exception as e:
|
|
print(f"Waiting for PostgreSQL database ({i+1}/{max_retries})...")
|
|
time.sleep(2)
|
|
else:
|
|
print("Database connection timeout.")
|
|
sys.exit(1)
|
|
|
|
from app import create_app
|
|
from app.extensions import db
|
|
from app.models.user import User
|
|
from app.shell_commands import create_admin_user
|
|
|
|
app = create_app()
|
|
with app.app_context():
|
|
db.create_all()
|
|
if User.query.filter_by(id=1).first() is None:
|
|
try:
|
|
create_admin_user()
|
|
except Exception as e:
|
|
print(f"Admin initialization notice: {e}")
|
|
PYEOF
|
|
|
|
echo "Version - $(python3 -c 'import app.build_version as v; print(v.BUILD_HASH)') (prod)"
|
|
echo "Running Vortexi OSS at $(date)"
|
|
exec gunicorn -b 0.0.0.0:3003 --preload --workers=4 --threads=10 "app:create_app()"
|