Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minecraft Server on AWS (Infrastructure as Code)

Provisions and runs a Minecraft Java Edition server on AWS ECS Fargate using Terraform and a Docker image. The world is stored on EFS so it survives restarts. The whole thing is deployed from the command line (or GitHub Actions) without using the AWS Management Console.

Background

The server runs as a container on Fargate instead of a managed EC2 instance. Terraform builds the networking, an ECR repository, an EFS file system, the ECS cluster, and the service. A Docker image holds the server; the world data is mounted from EFS at /data. The ECS service keeps one task running and replaces it automatically if it stops, which covers the auto-restart requirement. On shutdown ECS sends SIGTERM to the container, where the JVM runs as PID 1 and saves the world before exiting.

Pipeline

Dockerfile --build/push--> ECR image
Terraform --provisions--> EFS + ECS Fargate service (+ security groups, logs)
ECS task --public IP--> port 25565
AWS CLI --resolves IP--> nmap -sV -Pn -p T:25565 <ip>
flowchart TD
A[Dockerfile] -->|build + push| B[(ECR image)]
C[Terraform] -->|provisions| D[ECS Fargate service]
B --> D
C --> E[(EFS world volume)]
D -->|mounts /data| E
D -->|public IP :25565| F[nmap]
Loading

Requirements

Run from Linux or WSL2 on Windows. Install:

  • Terraform >= 1.6
  • AWS CLI v2
  • Docker
  • nmap

Configure AWS credentials with aws configure (region us-west-2). Verify with aws sts get-caller-identity.

By default the stack creates its own IAM roles. In an AWS Academy Learner Lab, which does not allow creating roles, create terraform/terraform.tfvars with:

create_iam_roles=falseexisting_role_name="LabRole"

Usage

./scripts/deploy.sh # build image, push to ECR, provision everything
./scripts/connect.sh # resolve the server IP and run the nmap check
./scripts/destroy.sh # tear everything down

deploy.sh initializes Terraform, creates the ECR repository, builds and pushes the image, then applies the rest of the stack. connect.sh waits for the task to start, finds its public IP through the AWS CLI, and probes port 25565. Fargate assigns a new IP each time the task starts, so re-run connect.sh after a redeploy.

Connecting

After connect.sh prints Server: <ip>:25565, join from the Minecraft client (Multiplayer > Add Server > paste the IP), or confirm reachability with:

nmap -sV -Pn -p T:25565 <ip>

GitHub Actions

  • .github/workflows/validate.yml runs terraform fmt, validate, and a Docker build on every push.
  • .github/workflows/deploy.yml runs the full deploy on push to main. It needs the repository secrets AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Layout

docker/ Dockerfile + entrypoint
terraform/ main, network, storage, iam, ecs, variables, outputs
scripts/ deploy, connect, destroy
.github/ CI workflows

Sources

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - breadonb/minecraft-iac · GitHub
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minecraft Server on AWS (Infrastructure as Code)

Provisions and runs a Minecraft Java Edition server on AWS ECS Fargate using Terraform and a Docker image. The world is stored on EFS so it survives restarts. The whole thing is deployed from the command line (or GitHub Actions) without using the AWS Management Console.

Background

The server runs as a container on Fargate instead of a managed EC2 instance. Terraform builds the networking, an ECR repository, an EFS file system, the ECS cluster, and the service. A Docker image holds the server; the world data is mounted from EFS at /data. The ECS service keeps one task running and replaces it automatically if it stops, which covers the auto-restart requirement. On shutdown ECS sends SIGTERM to the container, where the JVM runs as PID 1 and saves the world before exiting.

Pipeline

Dockerfile --build/push--> ECR image
Terraform --provisions--> EFS + ECS Fargate service (+ security groups, logs)
ECS task --public IP--> port 25565
AWS CLI --resolves IP--> nmap -sV -Pn -p T:25565 <ip>
flowchart TD
A[Dockerfile] -->|build + push| B[(ECR image)]
C[Terraform] -->|provisions| D[ECS Fargate service]
B --> D
C --> E[(EFS world volume)]
D -->|mounts /data| E
D -->|public IP :25565| F[nmap]
Loading

Requirements

Run from Linux or WSL2 on Windows. Install:

  • Terraform >= 1.6
  • AWS CLI v2
  • Docker
  • nmap

Configure AWS credentials with aws configure (region us-west-2). Verify with aws sts get-caller-identity.

By default the stack creates its own IAM roles. In an AWS Academy Learner Lab, which does not allow creating roles, create terraform/terraform.tfvars with:

create_iam_roles=falseexisting_role_name="LabRole"

Usage

./scripts/deploy.sh # build image, push to ECR, provision everything
./scripts/connect.sh # resolve the server IP and run the nmap check
./scripts/destroy.sh # tear everything down

deploy.sh initializes Terraform, creates the ECR repository, builds and pushes the image, then applies the rest of the stack. connect.sh waits for the task to start, finds its public IP through the AWS CLI, and probes port 25565. Fargate assigns a new IP each time the task starts, so re-run connect.sh after a redeploy.

Connecting

After connect.sh prints Server: <ip>:25565, join from the Minecraft client (Multiplayer > Add Server > paste the IP), or confirm reachability with:

nmap -sV -Pn -p T:25565 <ip>

GitHub Actions

  • .github/workflows/validate.yml runs terraform fmt, validate, and a Docker build on every push.
  • .github/workflows/deploy.yml runs the full deploy on push to main. It needs the repository secrets AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Layout

docker/ Dockerfile + entrypoint
terraform/ main, network, storage, iam, ecs, variables, outputs
scripts/ deploy, connect, destroy
.github/ CI workflows

Sources

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - breadonb/minecraft-iac · GitHub
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minecraft Server on AWS (Infrastructure as Code)

Provisions and runs a Minecraft Java Edition server on AWS ECS Fargate using Terraform and a Docker image. The world is stored on EFS so it survives restarts. The whole thing is deployed from the command line (or GitHub Actions) without using the AWS Management Console.

Background

The server runs as a container on Fargate instead of a managed EC2 instance. Terraform builds the networking, an ECR repository, an EFS file system, the ECS cluster, and the service. A Docker image holds the server; the world data is mounted from EFS at /data. The ECS service keeps one task running and replaces it automatically if it stops, which covers the auto-restart requirement. On shutdown ECS sends SIGTERM to the container, where the JVM runs as PID 1 and saves the world before exiting.

Pipeline

Dockerfile --build/push--> ECR image
Terraform --provisions--> EFS + ECS Fargate service (+ security groups, logs)
ECS task --public IP--> port 25565
AWS CLI --resolves IP--> nmap -sV -Pn -p T:25565 <ip>
flowchart TD
A[Dockerfile] -->|build + push| B[(ECR image)]
C[Terraform] -->|provisions| D[ECS Fargate service]
B --> D
C --> E[(EFS world volume)]
D -->|mounts /data| E
D -->|public IP :25565| F[nmap]
Loading

Requirements

Run from Linux or WSL2 on Windows. Install:

  • Terraform >= 1.6
  • AWS CLI v2
  • Docker
  • nmap

Configure AWS credentials with aws configure (region us-west-2). Verify with aws sts get-caller-identity.

By default the stack creates its own IAM roles. In an AWS Academy Learner Lab, which does not allow creating roles, create terraform/terraform.tfvars with:

create_iam_roles=falseexisting_role_name="LabRole"

Usage

./scripts/deploy.sh # build image, push to ECR, provision everything
./scripts/connect.sh # resolve the server IP and run the nmap check
./scripts/destroy.sh # tear everything down

deploy.sh initializes Terraform, creates the ECR repository, builds and pushes the image, then applies the rest of the stack. connect.sh waits for the task to start, finds its public IP through the AWS CLI, and probes port 25565. Fargate assigns a new IP each time the task starts, so re-run connect.sh after a redeploy.

Connecting

After connect.sh prints Server: <ip>:25565, join from the Minecraft client (Multiplayer > Add Server > paste the IP), or confirm reachability with:

nmap -sV -Pn -p T:25565 <ip>

GitHub Actions

  • .github/workflows/validate.yml runs terraform fmt, validate, and a Docker build on every push.
  • .github/workflows/deploy.yml runs the full deploy on push to main. It needs the repository secrets AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Layout

docker/ Dockerfile + entrypoint
terraform/ main, network, storage, iam, ecs, variables, outputs
scripts/ deploy, connect, destroy
.github/ CI workflows

Sources

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - breadonb/minecraft-iac · GitHub
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minecraft Server on AWS (Infrastructure as Code)

Provisions and runs a Minecraft Java Edition server on AWS ECS Fargate using Terraform and a Docker image. The world is stored on EFS so it survives restarts. The whole thing is deployed from the command line (or GitHub Actions) without using the AWS Management Console.

Background

The server runs as a container on Fargate instead of a managed EC2 instance. Terraform builds the networking, an ECR repository, an EFS file system, the ECS cluster, and the service. A Docker image holds the server; the world data is mounted from EFS at /data. The ECS service keeps one task running and replaces it automatically if it stops, which covers the auto-restart requirement. On shutdown ECS sends SIGTERM to the container, where the JVM runs as PID 1 and saves the world before exiting.

Pipeline

Dockerfile --build/push--> ECR image
Terraform --provisions--> EFS + ECS Fargate service (+ security groups, logs)
ECS task --public IP--> port 25565
AWS CLI --resolves IP--> nmap -sV -Pn -p T:25565 <ip>
flowchart TD
A[Dockerfile] -->|build + push| B[(ECR image)]
C[Terraform] -->|provisions| D[ECS Fargate service]
B --> D
C --> E[(EFS world volume)]
D -->|mounts /data| E
D -->|public IP :25565| F[nmap]
Loading

Requirements

Run from Linux or WSL2 on Windows. Install:

  • Terraform >= 1.6
  • AWS CLI v2
  • Docker
  • nmap

Configure AWS credentials with aws configure (region us-west-2). Verify with aws sts get-caller-identity.

By default the stack creates its own IAM roles. In an AWS Academy Learner Lab, which does not allow creating roles, create terraform/terraform.tfvars with:

create_iam_roles=falseexisting_role_name="LabRole"

Usage

./scripts/deploy.sh # build image, push to ECR, provision everything
./scripts/connect.sh # resolve the server IP and run the nmap check
./scripts/destroy.sh # tear everything down

deploy.sh initializes Terraform, creates the ECR repository, builds and pushes the image, then applies the rest of the stack. connect.sh waits for the task to start, finds its public IP through the AWS CLI, and probes port 25565. Fargate assigns a new IP each time the task starts, so re-run connect.sh after a redeploy.

Connecting

After connect.sh prints Server: <ip>:25565, join from the Minecraft client (Multiplayer > Add Server > paste the IP), or confirm reachability with:

nmap -sV -Pn -p T:25565 <ip>

GitHub Actions

  • .github/workflows/validate.yml runs terraform fmt, validate, and a Docker build on every push.
  • .github/workflows/deploy.yml runs the full deploy on push to main. It needs the repository secrets AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Layout

docker/ Dockerfile + entrypoint
terraform/ main, network, storage, iam, ecs, variables, outputs
scripts/ deploy, connect, destroy
.github/ CI workflows

Sources

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - breadonb/minecraft-iac · GitHub
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minecraft Server on AWS (Infrastructure as Code)

Provisions and runs a Minecraft Java Edition server on AWS ECS Fargate using Terraform and a Docker image. The world is stored on EFS so it survives restarts. The whole thing is deployed from the command line (or GitHub Actions) without using the AWS Management Console.

Background

The server runs as a container on Fargate instead of a managed EC2 instance. Terraform builds the networking, an ECR repository, an EFS file system, the ECS cluster, and the service. A Docker image holds the server; the world data is mounted from EFS at /data. The ECS service keeps one task running and replaces it automatically if it stops, which covers the auto-restart requirement. On shutdown ECS sends SIGTERM to the container, where the JVM runs as PID 1 and saves the world before exiting.

Pipeline

Dockerfile --build/push--> ECR image
Terraform --provisions--> EFS + ECS Fargate service (+ security groups, logs)
ECS task --public IP--> port 25565
AWS CLI --resolves IP--> nmap -sV -Pn -p T:25565 <ip>
flowchart TD
A[Dockerfile] -->|build + push| B[(ECR image)]
C[Terraform] -->|provisions| D[ECS Fargate service]
B --> D
C --> E[(EFS world volume)]
D -->|mounts /data| E
D -->|public IP :25565| F[nmap]
Loading

Requirements

Run from Linux or WSL2 on Windows. Install:

  • Terraform >= 1.6
  • AWS CLI v2
  • Docker
  • nmap

Configure AWS credentials with aws configure (region us-west-2). Verify with aws sts get-caller-identity.

By default the stack creates its own IAM roles. In an AWS Academy Learner Lab, which does not allow creating roles, create terraform/terraform.tfvars with:

create_iam_roles=falseexisting_role_name="LabRole"

Usage

./scripts/deploy.sh # build image, push to ECR, provision everything
./scripts/connect.sh # resolve the server IP and run the nmap check
./scripts/destroy.sh # tear everything down

deploy.sh initializes Terraform, creates the ECR repository, builds and pushes the image, then applies the rest of the stack. connect.sh waits for the task to start, finds its public IP through the AWS CLI, and probes port 25565. Fargate assigns a new IP each time the task starts, so re-run connect.sh after a redeploy.

Connecting

After connect.sh prints Server: <ip>:25565, join from the Minecraft client (Multiplayer > Add Server > paste the IP), or confirm reachability with:

nmap -sV -Pn -p T:25565 <ip>

GitHub Actions

  • .github/workflows/validate.yml runs terraform fmt, validate, and a Docker build on every push.
  • .github/workflows/deploy.yml runs the full deploy on push to main. It needs the repository secrets AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Layout

docker/ Dockerfile + entrypoint
terraform/ main, network, storage, iam, ecs, variables, outputs
scripts/ deploy, connect, destroy
.github/ CI workflows

Sources

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - breadonb/minecraft-iac · GitHub
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minecraft Server on AWS (Infrastructure as Code)

Provisions and runs a Minecraft Java Edition server on AWS ECS Fargate using Terraform and a Docker image. The world is stored on EFS so it survives restarts. The whole thing is deployed from the command line (or GitHub Actions) without using the AWS Management Console.

Background

The server runs as a container on Fargate instead of a managed EC2 instance. Terraform builds the networking, an ECR repository, an EFS file system, the ECS cluster, and the service. A Docker image holds the server; the world data is mounted from EFS at /data. The ECS service keeps one task running and replaces it automatically if it stops, which covers the auto-restart requirement. On shutdown ECS sends SIGTERM to the container, where the JVM runs as PID 1 and saves the world before exiting.

Pipeline

Dockerfile --build/push--> ECR image
Terraform --provisions--> EFS + ECS Fargate service (+ security groups, logs)
ECS task --public IP--> port 25565
AWS CLI --resolves IP--> nmap -sV -Pn -p T:25565 <ip>
flowchart TD
A[Dockerfile] -->|build + push| B[(ECR image)]
C[Terraform] -->|provisions| D[ECS Fargate service]
B --> D
C --> E[(EFS world volume)]
D -->|mounts /data| E
D -->|public IP :25565| F[nmap]
Loading

Requirements

Run from Linux or WSL2 on Windows. Install:

  • Terraform >= 1.6
  • AWS CLI v2
  • Docker
  • nmap

Configure AWS credentials with aws configure (region us-west-2). Verify with aws sts get-caller-identity.

By default the stack creates its own IAM roles. In an AWS Academy Learner Lab, which does not allow creating roles, create terraform/terraform.tfvars with:

create_iam_roles=falseexisting_role_name="LabRole"

Usage

./scripts/deploy.sh # build image, push to ECR, provision everything
./scripts/connect.sh # resolve the server IP and run the nmap check
./scripts/destroy.sh # tear everything down

deploy.sh initializes Terraform, creates the ECR repository, builds and pushes the image, then applies the rest of the stack. connect.sh waits for the task to start, finds its public IP through the AWS CLI, and probes port 25565. Fargate assigns a new IP each time the task starts, so re-run connect.sh after a redeploy.

Connecting

After connect.sh prints Server: <ip>:25565, join from the Minecraft client (Multiplayer > Add Server > paste the IP), or confirm reachability with:

nmap -sV -Pn -p T:25565 <ip>

GitHub Actions

  • .github/workflows/validate.yml runs terraform fmt, validate, and a Docker build on every push.
  • .github/workflows/deploy.yml runs the full deploy on push to main. It needs the repository secrets AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Layout

docker/ Dockerfile + entrypoint
terraform/ main, network, storage, iam, ecs, variables, outputs
scripts/ deploy, connect, destroy
.github/ CI workflows

Sources

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - breadonb/minecraft-iac · GitHub
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minecraft Server on AWS (Infrastructure as Code)

Provisions and runs a Minecraft Java Edition server on AWS ECS Fargate using Terraform and a Docker image. The world is stored on EFS so it survives restarts. The whole thing is deployed from the command line (or GitHub Actions) without using the AWS Management Console.

Background

The server runs as a container on Fargate instead of a managed EC2 instance. Terraform builds the networking, an ECR repository, an EFS file system, the ECS cluster, and the service. A Docker image holds the server; the world data is mounted from EFS at /data. The ECS service keeps one task running and replaces it automatically if it stops, which covers the auto-restart requirement. On shutdown ECS sends SIGTERM to the container, where the JVM runs as PID 1 and saves the world before exiting.

Pipeline

Dockerfile --build/push--> ECR image
Terraform --provisions--> EFS + ECS Fargate service (+ security groups, logs)
ECS task --public IP--> port 25565
AWS CLI --resolves IP--> nmap -sV -Pn -p T:25565 <ip>
flowchart TD
A[Dockerfile] -->|build + push| B[(ECR image)]
C[Terraform] -->|provisions| D[ECS Fargate service]
B --> D
C --> E[(EFS world volume)]
D -->|mounts /data| E
D -->|public IP :25565| F[nmap]
Loading

Requirements

Run from Linux or WSL2 on Windows. Install:

  • Terraform >= 1.6
  • AWS CLI v2
  • Docker
  • nmap

Configure AWS credentials with aws configure (region us-west-2). Verify with aws sts get-caller-identity.

By default the stack creates its own IAM roles. In an AWS Academy Learner Lab, which does not allow creating roles, create terraform/terraform.tfvars with:

create_iam_roles=falseexisting_role_name="LabRole"

Usage

./scripts/deploy.sh # build image, push to ECR, provision everything
./scripts/connect.sh # resolve the server IP and run the nmap check
./scripts/destroy.sh # tear everything down

deploy.sh initializes Terraform, creates the ECR repository, builds and pushes the image, then applies the rest of the stack. connect.sh waits for the task to start, finds its public IP through the AWS CLI, and probes port 25565. Fargate assigns a new IP each time the task starts, so re-run connect.sh after a redeploy.

Connecting

After connect.sh prints Server: <ip>:25565, join from the Minecraft client (Multiplayer > Add Server > paste the IP), or confirm reachability with:

nmap -sV -Pn -p T:25565 <ip>

GitHub Actions

  • .github/workflows/validate.yml runs terraform fmt, validate, and a Docker build on every push.
  • .github/workflows/deploy.yml runs the full deploy on push to main. It needs the repository secrets AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Layout

docker/ Dockerfile + entrypoint
terraform/ main, network, storage, iam, ecs, variables, outputs
scripts/ deploy, connect, destroy
.github/ CI workflows

Sources

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages