Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ad0facb
Dockerfile created
anders88 Sep 22, 2025
2676f7a
Sops config file
anders88 Sep 24, 2025
f177f1c
Update Dockerfile and add .enc.env for environment variables; create …
Kullsyreholdig Sep 24, 2025
56b922d
Add support for optional PATH_PREFIX in servlet mappings and normaliz…
Kullsyreholdig Sep 24, 2025
8a2d76a
clean up old files
Kullsyreholdig Sep 24, 2025
dd39b06
working cdk stack
Kullsyreholdig Sep 24, 2025
48f2815
Add GitHub Actions workflow for CDK infrastructure deployment
Kullsyreholdig Sep 28, 2025
eb0d6fd
Add optional PATH_PREFIX support for context path and servlet mappings
Kullsyreholdig Sep 28, 2025
94feca6
Add input for branch reference in CDK deployment workflow
Kullsyreholdig Sep 28, 2025
c0cde96
Update cdk-deploy.yml
Kullsyreholdig Sep 28, 2025
289fbd6
sleepingpill.javazone.no from alb
Kullsyreholdig Sep 28, 2025
367c029
Merge remote-tracking branch 'refs/remotes/origin/awsdocker' into aws…
Kullsyreholdig Sep 28, 2025
afd52c6
Update greeting in index.html to specify ECS environment
Kullsyreholdig Sep 28, 2025
65066f1
Update moresleep-stack.ts
Kullsyreholdig Sep 28, 2025
d554475
Added webhooks
anders88 Oct 26, 2025
d478c89
A little adjustment to web hook
anders88 Oct 27, 2025
5ff8efa
Added 2026 config dates
anders88 Aug 19, 2026
0ecd1d0
chore: make master match the deployed awsdocker line
Alexanderamiri Oct 24, 2026
0e39396
fix(build): drop the duplicate maven-surefire-plugin declaration
Alexanderamiri Oct 24, 2026
03d8f46
ci(build): publish the edge image only from merged code
Alexanderamiri Oct 24, 2026
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
9 changes: 7 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
*
!target/*-with-dependencies.jar
.git
cdk/
target/
test/
node_modules/
*.md
LICENSE.txt
3 changes: 0 additions & 3 deletions .ebextensions/00-set-timezone.config

This file was deleted.

6 changes: 0 additions & 6 deletions .ebextensions/cw-logging.config

This file was deleted.

11 changes: 0 additions & 11 deletions .elasticbeanstalk/config.global.yml

This file was deleted.

3 changes: 3 additions & 0 deletions .github/workflows/maven.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,8 @@ jobs:
if-no-files-found: error
retention-days: 7

# Only merged code becomes :edge (other repos' local setups pull it, e.g.
# javaBin/submittheforce compose.yaml). Pull requests build and test only.
- name: Build and push docker image [edge]
if: github.event_name != 'pull_request'
run: docker buildx build --push -t ghcr.io/javabin/moresleep:edge --platform linux/amd64,linux/arm64 .
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ src/main/kotlin/no/anksoft
.DS_Store
.env
.postgres_data
cdk.out/
node_modules
43 changes: 34 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,41 @@
# Fetch the application jar from the target directory and rename it to application.jar
FROM amazoncorretto:21-al2023-headless AS fetch
# Build: docker build -t moresleep-app:latest .
# Run: docker run --name moresleep-container -p 5000:5000 moresleep-app:latest
# Check localhost:5000 and you should get a homepage
# Stage 1: Build the application
FROM maven:3.9.11-eclipse-temurin-21 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -Dmaven.test.skip=true

COPY target /target
RUN mv /target/*-with-dependencies.jar /target/application.jar
# Stage 2: Create the final runtime image
FROM eclipse-temurin:21-jre-jammy AS final

# Install SOPS
RUN curl -L -o /usr/local/bin/sops https://github.com/getsops/sops/releases/download/v3.10.2/sops-v3.10.2.linux.amd64 && \
chmod +x /usr/local/bin/sops

# Actual image to run the application
FROM amazoncorretto:21-al2023-headless
# Install unzip and curl
RUN apt-get update && \
apt-get install -y curl unzip && \
rm -rf /var/lib/apt/lists/*

EXPOSE 8082
# Install AWS CLI v2
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/awscliv2.zip" && \
unzip /tmp/awscliv2.zip -d /tmp && \
/tmp/aws/install && \
rm -rf /tmp/aws /tmp/awscliv2.zip

# Set environment variables
ENV DO_FLYWAY_MIGRATION=false
ENV RUN_FROM_JAR=true

COPY --from=fetch /target/application.jar /work/application.jar
WORKDIR /app
COPY --from=build /app/target/moresleep-0.0.1-jar-with-dependencies.jar app.jar
COPY ./conf/.enc.env /app/.enc.env

# Remove AWS profile from SOPS config to use container's AWS credentials
RUN sed -i 's/sops_kms__list_0__map_aws_profile=javabin/sops_kms__list_0__map_aws_profile=/' /app/.enc.env

CMD ["java", "-jar", "/work/application.jar"]
EXPOSE 5000
ENTRYPOINT ["sops", "exec-env", ".enc.env", "java -jar app.jar"]
10 changes: 10 additions & 0 deletions cdk/bin/stacks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

import * as cdk from 'aws-cdk-lib';
import { MoresleepStack } from '../lib/moresleep-stack.js';

const app = new cdk.App();
new MoresleepStack(app, 'moresleepstack', {
env: { account: '553637109631', region: 'eu-central-1' },
});


55 changes: 55 additions & 0 deletions cdk/cdk.context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"acknowledged-issue-numbers": [
34892
],
"vpc-provider:account=553637109631:filter.isDefault=true:region=eu-central-1:returnAsymmetricSubnets=true": {
"vpcId": "vpc-d55e68bc",
"vpcCidrBlock": "172.31.0.0/16",
"ownerAccountId": "553637109631",
"availabilityZones": [],
"subnetGroups": [
{
"name": "Public",
"type": "Public",
"subnets": [
{
"subnetId": "subnet-0347ca5488bd97167",
"cidr": "172.31.48.0/20",
"availabilityZone": "eu-central-1a",
"routeTableId": "rtb-f0626d99"
},
{
"subnetId": "subnet-19746c70",
"cidr": "172.31.0.0/20",
"availabilityZone": "eu-central-1a",
"routeTableId": "rtb-f0626d99"
},
{
"subnetId": "subnet-01210e22afbd300aa",
"cidr": "172.31.64.0/20",
"availabilityZone": "eu-central-1b",
"routeTableId": "rtb-f0626d99"
},
{
"subnetId": "subnet-35c1f74e",
"cidr": "172.31.16.0/20",
"availabilityZone": "eu-central-1b",
"routeTableId": "rtb-f0626d99"
},
{
"subnetId": "subnet-2f3d0c65",
"cidr": "172.31.32.0/20",
"availabilityZone": "eu-central-1c",
"routeTableId": "rtb-f0626d99"
},
{
"subnetId": "subnet-0f462674c4b62bd57",
"cidr": "172.31.80.0/20",
"availabilityZone": "eu-central-1c",
"routeTableId": "rtb-f0626d99"
}
]
}
]
}
}
87 changes: 87 additions & 0 deletions cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"app": "npx tsx bin/stacks.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
"@aws-cdk/aws-kms:aliasNameRef": true,
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false,
"@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false,
"@aws-cdk/aws-ecs:disableEcsImdsBlocking": true,
"@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true,
"@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true,
"@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true,
"@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true,
"@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true,
"@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true,
"@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true,
"@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true,
"@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": true,
"@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": true,
"@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": true,
"@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": true,
"@aws-cdk/core:enableAdditionalMetadataCollection": true
}
}
48 changes: 48 additions & 0 deletions cdk/lib/existing-resources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import { Construct } from 'constructs';
export interface ExistingResources {
vpc: ec2.IVpc;
existingListener: elbv2.IApplicationListener;
}

export function importExistingResources(scope: Construct): ExistingResources {
// Import existing VPC
const vpc = ec2.Vpc.fromLookup(scope, 'ImportedVPC', {
isDefault: true, // Assuming you're using the default VPC
});

// Import the existing ALB
const existingAlb =
elbv2.ApplicationLoadBalancer.fromApplicationLoadBalancerAttributes(
scope,
'ExistingALB',
{
loadBalancerArn:
'arn:aws:elasticloadbalancing:eu-central-1:553637109631:loadbalancer/app/Default-ALB/1c9b1a5fd7bded5e',
loadBalancerCanonicalHostedZoneId: 'Z215JYRZR1TBD5',
loadBalancerDnsName:
'Default-ALB-1235825687.eu-central-1.elb.amazonaws.com',
securityGroupId: 'sg-06d60bddabf369fb2',
vpc,
}
);

// Import existing listener
const existingListener =
elbv2.ApplicationListener.fromApplicationListenerAttributes(
scope,
'ExistingListener',
{
listenerArn:
'arn:aws:elasticloadbalancing:eu-central-1:553637109631:listener/app/Default-ALB/1c9b1a5fd7bded5e/b211e068a4b86a7b', // Replace with your listener ARN
securityGroup: existingAlb.connections.securityGroups[0],
}
);


return {
vpc,
existingListener,
};
}
77 changes: 77 additions & 0 deletions cdk/lib/moresleep-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as cdk from 'aws-cdk-lib';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import * as iam from 'aws-cdk-lib/aws-iam';
import { type Construct } from 'constructs';
import { importExistingResources } from './existing-resources';

const port = 5000;
const healthCheckPath = '/';
const priority = 15;
const desiredCount = 2;

export class MoresleepStack extends cdk.Stack {
constructor(scope: Construct, id: string, properties?: cdk.StackProps) {
super(scope, id, properties);

// Import existing resources
const { vpc, existingListener } = importExistingResources(this);


// Create ECS Cluster
const cluster = new ecs.Cluster(this, 'Cluster', {
vpc,
clusterName: 'moresleep-test',
});
// Create the Fargate service first
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef', {
memoryLimitMiB: 512,
cpu: 256,
});

// Attach the SOPS KMS policy to the task role usin arn

taskDefinition.taskRole.addManagedPolicy(
iam.ManagedPolicy.fromManagedPolicyArn(
this,
'SopsKmsPolicy',
'arn:aws:iam::553637109631:policy/sops-kms-policy'
)
);

// console.log pwd
console.log('Current working directory:', process.cwd());

taskDefinition.addContainer('web', {
image: ecs.ContainerImage.fromAsset('../', { file: 'Dockerfile' }),

portMappings: [{ containerPort: port }],
logging: new ecs.AwsLogDriver({ streamPrefix: 'web' }),
});

const service = new ecs.FargateService(this, 'Service', {
cluster,
taskDefinition,
desiredCount,
assignPublicIp: true,
circuitBreaker: { rollback: true },
});

// Create a target group and add it to the existing listener
const targetGroup = new elbv2.ApplicationTargetGroup(this, 'TargetGroup', {
vpc,
port,
protocol: elbv2.ApplicationProtocol.HTTP,
targets: [service],
healthCheck: {
path: healthCheckPath,
},
});

existingListener.addTargetGroups('AddTargetGroup', {
targetGroups: [targetGroup],
priority,
conditions: [elbv2.ListenerCondition.hostHeaders(['sleepingpill.javazone.no'])],
});
}
}
Loading
Loading