Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ __pycache__/
instance/
app/__pycache__/
.idea/
backup/
backup/
**/.terraform/*
*.hcl
*.tfstate
*.tfstate.*
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ copy --from=builder /app/wheels /wheels
run pip install --upgrade pip && pip install --no-cache /wheels/*
copy app app
copy migrations migrations
copy boot.sh config.py .
copy boot.sh config.py gunicorn_config.py .
expose 5000
run chown -R audiovault:audiovault .
user audiovault
Expand Down
2 changes: 2 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from flask_login import LoginManager
from flask_bcrypt import Bcrypt
from flask_mail import Mail
from flask_limiter import Limiter
from config import Config

app = Flask(__name__)
Expand All @@ -15,5 +16,6 @@
login = LoginManager(app)
bcrypt = Bcrypt(app)
mail = Mail(app)
limiter = Limiter(app=app, key_func=None)

from app import routes, models
3 changes: 2 additions & 1 deletion app/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from app import app, db, login
from app import app, db, login, limiter
from flask import render_template, redirect, url_for, request, send_file
from flask_login import current_user, login_user, logout_user, login_required
from .forms import *
Expand Down Expand Up @@ -159,6 +159,7 @@ def generate_description():

@app.route('/download/<id>')
@login_required
@limiter.limit(app.config['RATELIMIT_DOWNLOAD_ENDPOINT'], key_func=lambda: current_user.name)
def download(id):
file_path = db.session.scalar(db.select(Content.file_path).filter_by(id=id))
return send_file(file_path, as_attachment=True)
Expand Down
2 changes: 1 addition & 1 deletion boot.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash
flask db upgrade
exec gunicorn -b :5000 -t 0 --access-logfile - --error-logfile - app:app
exec gunicorn -c gunicorn_config.py app:app
2 changes: 2 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ class Config:
MAIL_SENDER = os.environ.get('MAIL_SENDER', 'audiovault@mail.com')
DISCORD_URL = os.environ.get('DISCORD_URL', 'https://discordapp.com/api/webhooks/')
SEND_UPLOAD_NOTIFICATION = int(os.environ.get('SEND_UPLOAD_NOTIFICATION', 0))
RATELIMIT_STORAGE_URI = os.environ.get('RATELIMIT_STORAGE_URI', 'memory://')
RATELIMIT_DOWNLOAD_ENDPOINT = os.environ.get('RATELIMIT_DOWNLOAD_ENDPOINT', '3 per minute')
5 changes: 4 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ services:
volumes:
- db-data:/var/lib/mysql:Z
app:
image: audiovault:0.2.9
image: audiovault:0.2.12
ports:
- "5000:5000"
depends_on:
Expand All @@ -23,9 +23,12 @@ services:
- DB_USER=root
- DB_PASSWORD=Password123!
- DB_NAME=audiovault
- RATELIMIT_STORAGE_URI=memcached://memcached:11211
volumes:
- movies:/home/audiovault/movies
- shows:/home/audiovault/shows
memcached:
image: bitnami/memcached:1.6.38-debian-12-r8
volumes:
db-data:
movies:
Expand Down
8 changes: 8 additions & 0 deletions gunicorn_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
workers = 1
worker_class = "gevent"
worker_connections = 1000
bind = ":5000"
max_requests = 1000
max_requests_jitter = 50
access_log = "-"
errorlog = "-"
35 changes: 35 additions & 0 deletions infra/cluster.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.31"

cluster_name = var.cluster_name
cluster_version = var.cluster_version
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
control_plane_subnet_ids = module.vpc.intra_subnets
cluster_endpoint_public_access = true
enable_cluster_creator_admin_permissions = true

eks_managed_node_groups = {
one = {
name = "${var.cluster_name}-ng1"
instance_types = ["t3.small"]
min_size = 2
max_size = 6
desired_size = 2
}
}
}

resource "kubernetes_namespace" "audiovault" {
metadata {
name = var.namespace
}
}

resource "null_resource" "update_kubeconfig" {
depends_on = [module.eks]
provisioner "local-exec" {
command = "aws eks update-kubeconfig --name ${var.cluster_name}"
}
}
69 changes: 69 additions & 0 deletions infra/efs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
locals {
service_account_efs = "efs-csi-controller"
}

module "efs_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
version = "~> 5.55.0"
role_name = "efs_csi_role"
attach_efs_csi_policy = true
oidc_providers = {
eks = {
provider_arn = module.eks.oidc_provider_arn
namespace_service_accounts = ["kube-system:${local.service_account_efs}"]
}
}
}

resource "helm_release" "aws_efs_csi_driver" {
chart = "aws-efs-csi-driver"
repository = "https://kubernetes-sigs.github.io/aws-efs-csi-driver/"
name = "aws-efs-csi-driver"
version = "3.1.9"
namespace = "kube-system"
set {
name = "image.repository"
value = "602401143452.dkr.ecr.${var.region}.amazonaws.com/eks/aws-efs-csi-driver"
}
set {
name = "controller.serviceAccount.create"
value = true
}
set {
name = "controller.serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
value = module.efs_role.iam_role_arn
}
set {
name = "controller.serviceAccount.name"
value = local.service_account_efs
}
}

resource "aws_security_group" "audiovault_efs_sg" {
name = "audiovault_efs_sg"
description = "Allow NFS access for EFS on port 2049"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 2049
to_port = 2049
protocol = "tcp"
cidr_blocks = [module.vpc.vpc_cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

resource "aws_efs_file_system" "audiovault_efs" {
creation_token = "efs_for_audiovault"
}

resource "aws_efs_mount_target" "audiovault_efs_mount" {
file_system_id = aws_efs_file_system.audiovault_efs.id
security_groups = [aws_security_group.audiovault_efs_sg.id]
for_each = toset(module.vpc.private_subnets)
subnet_id = each.key
}
23 changes: 23 additions & 0 deletions infra/elasticache.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
resource "aws_security_group" "audiovault_elasticache_sg" {
name = "audiovault_elasticache_sg"
description = "Allow access for Elasticache cluster on Port 11211"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 11211
to_port = 11211
protocol = "tcp"
cidr_blocks = [module.vpc.vpc_cidr_block]
}
}

resource "aws_elasticache_cluster" "audiovault_elasticache" {
cluster_id = "audiovault-elasticache"
engine = "memcached"
engine_version = "1.6.22"
node_type = "cache.t3.small"
num_cache_nodes = 2
parameter_group_name = "default.memcached1.6"
port = 11211
security_group_ids = [aws_security_group.audiovault_elasticache_sg.id]
subnet_group_name = module.vpc.elasticache_subnet_group_name
}
75 changes: 75 additions & 0 deletions infra/load_balancer.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
locals {
service_account_alb = "aws-load-balancer-controller"
}

module "lb_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
version = "~> 5.55.0"
role_name = "aws_load_balancer_controller_role"
attach_load_balancer_controller_policy = true
oidc_providers = {
eks = {
provider_arn = module.eks.oidc_provider_arn
namespace_service_accounts = ["kube-system:${local.service_account_alb}"]
}
}
}

resource "kubernetes_service_account" "alb_controller_sa" {
metadata {
name = local.service_account_alb
namespace = "kube-system"
labels = {
"app.kubernetes.io/name" = local.service_account_alb
"app.kubernetes.io/component" = "controller"
}
annotations = {
"eks.amazonaws.com/role-arn" = module.lb_role.iam_role_arn
"eks.amazonaws.com/sts-regional-endpoints" = "true"
}
}
}

resource "helm_release" "alb_controller" {
name = "aws-load-balancer-controller"
repository = "https://aws.github.io/eks-charts"
chart = "aws-load-balancer-controller"
version = "1.13.0"
namespace = "kube-system"
depends_on = [kubernetes_service_account.alb_controller_sa]
set {
name = "region"
value = var.region
}
set {
name = "vpcId"
value = module.vpc.vpc_id
}
set {
name = "image.repository"
value = "602401143452.dkr.ecr.${var.region}.amazonaws.com/amazon/aws-load-balancer-controller"
}
set {
name = "serviceAccount.create"
value = "false"
}
set {
name = "serviceAccount.name"
value = local.service_account_alb
}
set {
name = "clusterName"
value = var.cluster_name
}
}

module "eks-external-dns" {
source = "lablabs/eks-external-dns/aws"
version = "1.2.0"
cluster_identity_oidc_issuer = module.eks.cluster_oidc_issuer_url
cluster_identity_oidc_issuer_arn = module.eks.oidc_provider_arn
settings = {
"policy" = "sync"
}
depends_on = [module.eks]
}
14 changes: 14 additions & 0 deletions infra/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
output "db_endpoint" {
description = "rds db endpoint"
value = aws_db_instance.audiovault_rds.endpoint
}

output "efs_id" {
description = "EFS file system id"
value = aws_efs_file_system.audiovault_efs.id
}

output "elasticache_address" {
description = "Elasticache cluster address"
value = aws_elasticache_cluster.audiovault_elasticache.cluster_address
}
25 changes: 24 additions & 1 deletion infra/providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,34 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.83"
}
}
required_version = "~> 1.3"
}

provider aws {
region = "eu-north-1"
region = var.region
}

provider "kubernetes" {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
exec {
api_version = "client.authentication.k8s.io/v1beta1"
command = "aws"
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
}
}

provider "helm" {
kubernetes {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
exec {
api_version = "client.authentication.k8s.io/v1beta1"
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
command = "aws"
}
}
}
27 changes: 27 additions & 0 deletions infra/rds.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
resource "aws_security_group" "audiovault_rds_sg" {
name = "audiovault_rds_sg"
description = "Allow access for RDS Database on Port 3306"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = [module.vpc.vpc_cidr_block]
}
}

resource "aws_db_instance" "audiovault_rds" {
engine = "mariadb"
engine_version = "11.4"
db_name = "audiovault"
identifier = "audiovault"
instance_class = "db.t3.micro"
allocated_storage = 10
publicly_accessible = false
username = jsondecode(data.aws_secretsmanager_secret_version.current.secret_string)["db_user"]
password = jsondecode(data.aws_secretsmanager_secret_version.current.secret_string)["db_password"]
vpc_security_group_ids = [aws_security_group.audiovault_rds_sg.id]
skip_final_snapshot = true
db_subnet_group_name = module.vpc.database_subnet_group_name
multi_az = true
}
Loading