From 732667cf64a506bbd956997bb95cf7eea5504cac Mon Sep 17 00:00:00 2001 From: Stefano Date: Tue, 20 May 2025 12:45:55 -0500 Subject: [PATCH] Added SSL cert generation and installation. Moved variables to ENV --- .env.example | 3 +++ .gitea/workflows/aws_deploy_on_push.yml | 4 ++++ .vscode/settings.json | 3 +++ app.py | 23 ++++++++++++++++++++++- infrastructure/stack.py | 21 +++++++++++++++++++-- infrastructure/userdata.sh | 24 +++++++++++++++++++++++- scripts/deploy.sh | 13 ++++++++++++- scripts/destroy.sh | 17 ++++++++++++++++- 8 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b754e66 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +FREEDNS_User=MyFreeDNSUsername +FREEDNS_Password=MyFreeDNSPassword +DOMAIN_NAME=mydomain.com \ No newline at end of file diff --git a/.gitea/workflows/aws_deploy_on_push.yml b/.gitea/workflows/aws_deploy_on_push.yml index 59c884e..f188a44 100644 --- a/.gitea/workflows/aws_deploy_on_push.yml +++ b/.gitea/workflows/aws_deploy_on_push.yml @@ -39,6 +39,10 @@ jobs: - name: Deploy to AWS run: cdk deploy --app="python3 ${PWD}/app.py" --require-approval=never + env: + FREEDNS_User: ${{ secrets.FREEDNS_USER }} + FREEDNS_Password: ${{ secrets.FREEDNS_PASSWORD }} + DOMAIN_NAME: ${{ secrets.DOMAIN_NAME }} - name: Install AWS CLI run: | diff --git a/.vscode/settings.json b/.vscode/settings.json index ce6cd0f..256237f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,11 +11,14 @@ "dotenv", "fastapi", "fiorinis", + "freedns", + "fullchain", "gitea", "iptv", "nohup", "passlib", "pyjwt", + "reloadcmd", "starlette", "stefano", "uvicorn", diff --git a/app.py b/app.py index ea9d225..5c2f356 100644 --- a/app.py +++ b/app.py @@ -1,7 +1,28 @@ #!/usr/bin/env python3 +import os import aws_cdk as cdk from infrastructure.stack import IptvUpdaterStack app = cdk.App() -IptvUpdaterStack(app, "IptvUpdater") + +# Read environment variables for FreeDNS credentials +freedns_user = os.environ.get("FREEDNS_User") +freedns_password = os.environ.get("FREEDNS_Password") +domain_name = os.environ.get("DOMAIN_NAME") + +if not freedns_user or not freedns_password: + raise ValueError("FREEDNS_User and FREEDNS_Password environment variables must be set.") + +if not domain_name: + raise ValueError("DOMAIN_NAME environment variable must be set.") + +IptvUpdaterStack(app, "IptvUpdaterStack", + freedns_user=freedns_user, + freedns_password=freedns_password, + domain_name=domain_name, + # If you don't specify 'env', the stack will be deployed to the account and region that are + # configured in your AWS CLI profile. Defaulting to the environment where the CLI is configured. + # env=cdk.Environment(account=os.getenv('CDK_DEFAULT_ACCOUNT'), region=os.getenv('CDK_DEFAULT_REGION')), +) + app.synth() \ No newline at end of file diff --git a/infrastructure/stack.py b/infrastructure/stack.py index 38983a5..540b50a 100644 --- a/infrastructure/stack.py +++ b/infrastructure/stack.py @@ -11,7 +11,15 @@ from aws_cdk import ( from constructs import Construct class IptvUpdaterStack(Stack): - def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: + def __init__( + self, + scope: Construct, + construct_id: str, + freedns_user: str, + freedns_password: str, + domain_name: str, + **kwargs + ) -> None: super().__init__(scope, construct_id, **kwargs) # Create VPC @@ -151,11 +159,20 @@ class IptvUpdaterStack(Stack): # Creates a userdata object for Linux hosts userdata = ec2.UserData.for_linux() + + # Add environment variables for acme.sh from parameters + userdata.add_commands( + f'export FREEDNS_User="{freedns_user}"', + f'export FREEDNS_Password="{freedns_password}"', + f'export DOMAIN_NAME="{domain_name}"' + ) + # Adds one or more commands to the userdata object. userdata.add_commands( f'echo "COGNITO_USER_POOL_ID={user_pool.user_pool_id}" >> /etc/environment', f'echo "COGNITO_CLIENT_ID={client.user_pool_client_id}" >> /etc/environment', - f'echo "COGNITO_CLIENT_SECRET={client.user_pool_client_secret.to_string()}" >> /etc/environment' + f'echo "COGNITO_CLIENT_SECRET={client.user_pool_client_secret.to_string()}" >> /etc/environment', + f'echo "DOMAIN_NAME={domain_name}" >> /etc/environment' ) userdata.add_commands(str(userdata_file, 'utf-8')) diff --git a/infrastructure/userdata.sh b/infrastructure/userdata.sh index 4d6e37b..b528b51 100644 --- a/infrastructure/userdata.sh +++ b/infrastructure/userdata.sh @@ -32,11 +32,33 @@ Restart=always WantedBy=multi-user.target EOF +# Install and configure acme.sh +curl https://get.acme.sh | sh -s email=stefano@fiorinis.com + +# Configure acme.sh to use DNS API for FreeDNS +. "/root/.acme.sh/acme.sh.env" +acme.sh --issue --dns dns_freedns -d ${DOMAIN_NAME} -d *.${DOMAIN_NAME} +sudo mkdir -p /etc/nginx/ssl +acme.sh --install-cert -d ${DOMAIN_NAME} -d *.${DOMAIN_NAME} \ + --key-file /etc/nginx/ssl/${DOMAIN_NAME}.pem \ + --fullchain-file /etc/nginx/ssl/cert.pem \ + --reloadcmd "service nginx force-reload" + # Create nginx config cat << 'EOF' > /etc/nginx/conf.d/iptvUpdater.conf server { listen 80; - server_name $HOSTNAME; + server_name ${DOMAIN_NAME} *.${DOMAIN_NAME}; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name ${DOMAIN_NAME} *.${DOMAIN_NAME}; + + ssl_certificate /etc/nginx/ssl/cert.pem; + ssl_certificate_key /etc/nginx/ssl/${DOMAIN_NAME}.pem; + location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; diff --git a/scripts/deploy.sh b/scripts/deploy.sh index c2eb516..098434f 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,7 +1,18 @@ #!/bin/bash +# Load environment variables from .env file if it exists +if [ -f .env ]; then + export $(cat .env | xargs) +fi + +# Check if required environment variables are set +if [ -z "$FREEDNS_User" ] || [ -z "$FREEDNS_Password" ] || [ -z "$DOMAIN_NAME" ]; then + echo "Error: FREEDNS_User, FREEDNS_Password, and DOMAIN_NAME must be set as environment variables or in a .env file." + exit 1 +fi + # Deploy infrastructure -cdk deploy +cdk deploy --app="python3 ${PWD}/app.py" # Update application on running instances INSTANCE_IDS=$(aws ec2 describe-instances \ diff --git a/scripts/destroy.sh b/scripts/destroy.sh index bde6947..141e61e 100755 --- a/scripts/destroy.sh +++ b/scripts/destroy.sh @@ -1,4 +1,19 @@ #!/bin/bash +# Load environment variables from .env file if it exists +if [ -f ${PWD}/.env ]; then + export $(cat ${PWD}/.env | xargs) +fi + +# Check if required environment variables are set +if [ -z "$FREEDNS_User" ] || [ -z "$FREEDNS_Password" ] || [ -z "$DOMAIN_NAME" ]; then + echo "Error: FREEDNS_User, FREEDNS_Password, and DOMAIN_NAME must be set as environment variables or in a .env file." + exit 1 +fi + +# Optional: Print the variables being used (for verification) +echo "Using DOMAIN_NAME: $DOMAIN_NAME" +echo "Using FREEDNS_User: $FREEDNS_User" # Be cautious printing passwords + # Destroy infrastructure -cdk destroy --force \ No newline at end of file +cdk destroy --app="python3 ${PWD}/app.py" --force \ No newline at end of file