Compare commits

..

10 Commits

Author SHA1 Message Date
Joe Tretter
714c4f6ed4 Add some comments into the image build batch to show how to proceed further after the image is built. 2023-02-16 14:42:03 -06:00
Joe Tretter
3d00a07e41 give everything a name. 2022-09-30 15:59:36 -05:00
Joe Tretter
9b25fa2eda cleanup directory strucutre and fine tune 2022-09-30 10:55:07 -05:00
Joe Tretter
dae7fbc9e7 Finished up with Ubuntu 2022-09-29 18:34:21 -05:00
Joe Tretter
519b3378b1 Ubuntu server works. 2022-09-29 16:45:35 -05:00
Joe Tretter
b50c7e9ddc Adding some docker and terraform to it ... wip 2022-09-29 13:39:46 -05:00
Joe Tretter
e359485d94 proper post and put handling 2020-08-29 23:12:27 -05:00
Joe Tretter
89bd55c83b - Save to file after every modification request. 2020-08-29 14:15:55 -05:00
Joe Tretter
e546e17c7e - Adding a couple more headers required for things to work. 2020-08-29 13:18:37 -05:00
Joe Tretter
ecd004e2ca - Handle OPTIONS request 2020-08-29 01:13:06 -05:00
19 changed files with 611 additions and 175 deletions

34
.gitignore vendored
View File

@@ -1 +1,33 @@
data
app/dataDir/*
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Include override files you do wish to add to version control using negated pattern
#
# !example_override.tf
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*
dumbserver.image.tar

37
README Normal file
View File

@@ -0,0 +1,37 @@
I am taking this as a test project for docker and terraform too...
The Terraform part is on the more "enterprise" side with not only just a public IP on the EC2.
for the docker imaging look at: https://www.fosstechnix.com/how-to-create-docker-image-for-node-js-application/
The docker image can be built with
podman build -t dumbserver .
the image then can be extracted with
podman image save -o dumbserver.image.tar dumbserver
on the target machine it can be imported with
podman image load -i dumbserer.image.tar
and running a container with the image id done via:
podman run --name dumbserver -p 1280:1280 dumbserver
(Port 1280 is what it listens on)
updating the image from a local file (in podman):
podman pull oci-archive:/tmp/dumbserver.image.tar
then the container needs to be re-created... stop/rm/run
At this stage, terraform will create an ssh accessable server (key is in "terraformtest1.ppk") - tutorial used for that: https://medium.com/@hmalgewatta/setting-up-an-aws-ec2-instance-with-ssh-access-using-terraform-c336c812322f
As part of the terraform, I copy a script to install docker/podman - and upload the image
then I set up the container and start it. that's it.
initialize with
terraform init
then plan
terraform plan
then apply
terraform apply
To read the terraform output into powershell use
$Json_Output = (& terraform output -json) | ConvertFrom-Json

18
app/Dockerfile Normal file
View File

@@ -0,0 +1,18 @@
FROM node:current-slim
# To Create nodejsapp directory
WORKDIR /nodejsapp
# To Install All dependencies
COPY package*.json .
RUN npm install
# To copy all application packages
COPY . .
# expose the data dir as a volume
VOLUME [ "dataDir" ]
# Expose port 1280 and Run the server.js file to start node js application
EXPOSE 1280
CMD [ "node", "dumbserver.js" ]

233
app/dumbserver.js Normal file
View File

@@ -0,0 +1,233 @@
//
// Dependencies
//
let http = require("http");
let fs = require("fs");
//
// Constants
//
let DATA_LOCATION = "dataDir/data"; // both the url root and the location of data file
let DATA_LOCATION_LEN = DATA_LOCATION.length;
let DATA_FILE = __dirname + "/" + DATA_LOCATION;
let PORT = 1280;
//
// Load store file
//
let store = {}; // deafult empty object
let json = "";
try {
let json = fs.readFileSync(DATA_FILE);
store = JSON.parse(json);
console.log("Read store file");
} catch (e) {
// lazy error handling
console.log("Could not load store file. Using empty array.");
}
//
// Flush to store file on exit
//
let flush = function () {
console.log("Flushing data to file [" + DATA_FILE + "]\n");
fs.writeFileSync(DATA_FILE, JSON.stringify(store));
};
let handleInterrupt = function () {
flush();
process.exit();
};
process.on("SIGINT", handleInterrupt);
process.on("SIGTERM", handleInterrupt);
process.on("SIGHUP", flush); // HUP flushes to file but keeps the server running
//
// If request URI is prefixed with the value of DATA_LOCATION, we treat incoming request as a REST request
// Otherwise we serve the file referenced by the URI
//
let serveFile = function (loc, req, resp) {
let fullPath = __dirname + "/" + loc;
console.log("Trying to serve file at [" + fullPath + "]");
if (req.method !== "GET") {
// read only!
resp.writeHead(405);
resp.write("Unsupported method\n");
resp.end();
} else if (fs.existsSync(fullPath)) {
resp.writeHead(200);
fs.createReadStream(fullPath).pipe(resp);
} else {
resp.writeHead(404);
resp.write("Not Found\n");
resp.end();
}
};
let serveRestData = function (urlPath, req, resp) {
console.log(req.method + " request for path [" + urlPath + "]");
switch (req.method) {
case "GET":
let exactMatch = !urlPath.endsWith("/");
let matchFound = false;
if (exactMatch) {
// assumes that only a single resource has this ID.
console.log(" - Exact Match.");
if (store.hasOwnProperty(urlPath)) {
resp.writeHead(200, { "Content-Type": "application/json" });
resp.write(JSON.stringify(store[urlPath]) + "\n");
matchFound = true;
}
} else {
console.log(" - All Matches.");
let matches = [];
Object.keys(store).forEach((theKey) => {
if (theKey.startsWith(urlPath)) {
matches.push(store[theKey]);
matchFound = true;
}
});
if (matchFound) {
resp.writeHead(200, { "Content-Type": "application/json" });
resp.write(JSON.stringify(matches));
}
}
if (!matchFound) {
console.log(" - Match NOT found.");
resp.writeHead(404, { "Content-Type": "application/json" });
resp.write('{"success":false, "error":"Not Found"}');
} else {
console.log(" - Match found.");
}
resp.end();
break;
case "PUT":
json = "";
req.on("data", function (chunk) {
json += chunk;
});
req.on("end", function () {
try {
let data = JSON.parse(json);
store[urlPath] = data;
resp.writeHead(201, { "Content-Type": "application/json" });
resp.write('{"success":true}');
} catch (e) {
resp.writeHead(400, { "Content-Type": "application/json" });
resp.write('{"success":false, "error":"Invalid JSON"}');
}
resp.end();
flush();
});
break;
case "POST":
json = "";
req.on("data", function (chunk) {
json += chunk;
});
req.on("end", function () {
try {
let data = JSON.parse(json);
if (data.ID === undefined) {
resp.writeHead(400, { "Content-Type": "application/json" });
resp.write('{"success":false, "error":"The ID Field needs to be given"}');
} else {
// make sure the ID from the data is used as the final resource Identifier,
// even if the URL has none or says different.
let re = new RegExp("/[^/]*$");
urlPath = urlPath.replace(re, "");
urlPath = urlPath + "/" + data.ID;
console.log(" - storing with resource key: [" + urlPath + "]");
store[urlPath] = data;
resp.writeHead(201, { "Content-Type": "application/json" });
resp.write(JSON.stringify(store[urlPath]));
}
} catch (e) {
resp.writeHead(400, { "Content-Type": "application/json" });
resp.write('{"success":false, "error":"Invalid JSON"}');
}
resp.end();
flush();
});
break;
case "PATCH":
json = "";
req.on("data", function (chunk) {
json += chunk;
});
req.on("end", function () {
try {
let data = JSON.parse(json);
Object.keys(data).forEach((theKey) => {
store[urlPath][theKey] = data[theKey];
});
resp.writeHead(201, { "Content-Type": "application/json" });
resp.write('{"success":true}');
} catch (e) {
resp.writeHead(400, { "Content-Type": "application/json" });
resp.write('{"success":false, "error":"Invalid JSON"}');
}
resp.end();
flush();
});
break;
case "OPTIONS":
resp.end();
break;
case "DELETE":
if (store.hasOwnProperty(urlPath)) {
delete store[urlPath];
resp.writeHead(204, { "Content-Type": "application/json" });
resp.write('{"success":true}');
} else {
resp.writeHead(404, { "Content-Type": "application/json" });
resp.write('{"success":false, "error":"Not Found"}');
}
resp.end();
flush();
break;
default:
resp.writeHead(405, { "Content-Type": "application/json" });
resp.write('{"success":false, "error":"Unsupported method"}');
resp.end();
}
};
//
// Listen for connections
//
http
.createServer(function (req, resp) {
// CORS headers
resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Headers", "X-Request-With, content-type");
resp.setHeader("Vary", "Origin");
resp.setHeader("Access-Control-Allow-Methods", "GET, PATCH, POST, PUT, DELETE, OPTIONS");
console.log("Serving [" + req.url + "]");
if (req.url === "/") {
// server index file
serveFile("index.html", req, resp);
} else {
// rest request
serveRestData(req.url, req, resp);
}
})
.listen(PORT);

9
app/index.html Normal file
View File

@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
Dumbserver
</head>
<body>
<p>Server version: 2022-09-30_10_21_17</p>
</body>
</html>

19
app/package.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "dumbserver",
"version": "1.0.0",
"description": "",
"main": "dumbserver.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/noelbennett/dumbserver.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/noelbennett/dumbserver/issues"
},
"homepage": "https://github.com/noelbennett/dumbserver#readme"
}

23
docker/buildimage.cmd Normal file
View File

@@ -0,0 +1,23 @@
docker build -t dumbserver ../app/
docker image save -o dumbserver.image.tar dumbserver
# [root@podhost tmp]# podman image load --input dumbserver.image.tar
# Getting image source signatures
# Copying blob b45078e74ec9 done
# Copying blob b34a262752ce done
# Copying blob 06cdaeea8c1e done
# Copying blob 192b450771fa done
# Copying blob 273c8cbf7fe9 done
# Copying blob 222ecd8c2394 done
# Copying blob b243f76c651c done
# Copying blob 7c655cb7234e done
# Copying blob ef546e9fb70f done
# Copying config e9ffb6042a done
# Writing manifest to image destination
# Storing signatures
# Loaded image: localhost/dumbserver:latest
# [root@podhost tmp]# podman image ls
# REPOSITORY TAG IMAGE ID CREATED SIZE
# localhost/dumbserver latest e9ffb6042ab0 4 months ago 248 MB
# docker.io/nodered/node-red latest a15fc0f4e930 6 months ago 492 MB
# [root@podhost tmp]# podman run -d -v /home/podman/dubserverData:/nodejsapp/dataDir -p 1280:1280 --name=dumbserver dumbserver

View File

@@ -1,166 +0,0 @@
//
// Dependencies
//
let http = require('http');
let fs = require('fs');
//
// Constants
//
let DATA_LOCATION = 'data'; // both the url root and the location of data file
let DATA_LOCATION_LEN = DATA_LOCATION.length;
let DATA_FILE = __dirname + '/' + DATA_LOCATION;
let PORT = 1280;
//
// Load store file
//
let store = {}; // deafult empty object
try {
let json = fs.readFileSync(DATA_FILE);
store = JSON.parse(json);
console.log('Read store file');
} catch (e) { // lazy error handling
console.log('Could not load store file. Using empty array.');
}
//
// Flush to store file on exit
//
let flush = function()
{
console.log('Caught deadly signal.');
console.log('Flushing data to file [' + DATA_FILE + ']\n');
fs.writeFileSync(DATA_FILE, JSON.stringify(store));
};
let handleInterrupt = function() { flush(); process.exit(); };
process.on('SIGINT', handleInterrupt);
process.on('SIGTERM', handleInterrupt);
process.on('SIGHUP', flush); // HUP flushes to file but keeps the server running
//
// If request URI is prefixed with the value of DATA_LOCATION, we treat incoming request as a REST request
// Otherwise we serve the file referenced by the URI
//
let serveFile = function(loc, req, resp) {
let fullPath = __dirname + '/' + loc;
console.log('Trying to serve file at [' + fullPath + ']');
if (req.method !== 'GET') { // read only!
resp.writeHead(405);
resp.write('Unsupported method\n');
resp.end();
} else if (fs.existsSync(fullPath)) {
resp.writeHead(200);
fs.createReadStream(fullPath).pipe(resp);
} else {
resp.writeHead(404);
resp.write('Not Found\n');
resp.end();
}
};
let serveRestData = function(key, req, resp) {
console.log(req.method + ' request for key [' + key + ']');
switch (req.method) {
case 'GET':
let exactMatch=!key.endsWith('/');
let matchFound=false;
if (exactMatch) {
console.log(" - Exact Match.");
if (store.hasOwnProperty(key)) {
resp.writeHead(200, { 'Content-Type' : 'application/json' });
resp.write(JSON.stringify(store[key]) + '\n');
matchFound=true;
}
} else {
console.log(" - All Matches.");
let matches=[];
Object.keys(store).forEach(theKey=>{
if (theKey.startsWith(key)){
matches.push(store[theKey]);
matchFound=true;
}
});
if (matchFound) {
resp.writeHead(200, { 'Content-Type' : 'application/json' });
resp.write(JSON.stringify(matches));
}
}
if (!matchFound) {
console.log(" - Match NOT found.");
resp.writeHead(404, { 'Content-Type' : 'application/json' });
resp.write('{"success":false, "error":"Not Found"}');
} else {
console.log(" - Match not found.");
}
resp.end();
break;
case 'PUT':
case 'POST':
let json = '';
req.on('data', function(chunk) { json += chunk; });
req.on('end', function() {
try {
let data = JSON.parse(json);
store[key] = data;
resp.writeHead(201, { 'Content-Type' : 'application/json' });
resp.write('{"success":true}');
} catch (e) {
resp.writeHead(400, { 'Content-Type' : 'application/json' });
resp.write('{"success":false, "error":"Invalid JSON"}');
}
resp.end();
});
break;
case 'DELETE':
if (store.hasOwnProperty(key)) {
delete store[key];
resp.writeHead(204, { 'Content-Type' : 'application/json' });
resp.write('{"success":true}');
} else {
resp.writeHead(404, { 'Content-Type' : 'application/json' });
resp.write('{"success":false, "error":"Not Found"}');
}
resp.end();
flush();
break;
default:
resp.writeHead(405, { 'Content-Type' : 'application/json' });
resp.write('{"success":false, "error":"Unsupported method"}');
resp.end();
}
};
//
// Listen for connections
//
http.createServer(function(req, resp) {
// CORS headers
resp.setHeader('Access-Control-Allow-Origin', '*');
resp.setHeader('Vary', 'Origin');
let uri = req.url //.replace(/^\/+|\/+$/g, ''); // trim slashes
console.log('Serving [' + req.url + ']');
if (uri === '/') { // server index file
uri = 'index.html';
serveFile(uri, req, resp);
} else { // rest request
serveRestData(req.url, req, resp);
}
}).listen(PORT);

View File

@@ -1,8 +0,0 @@
<!doctype html>
<html>
<head>
</head>
<body>
<p>Hello World!</p>
</body>
</html>

26
teraformtest1.ppk Normal file
View File

@@ -0,0 +1,26 @@
PuTTY-User-Key-File-2: ssh-rsa
Encryption: none
Comment: teraformtest1
Public-Lines: 6
AAAAB3NzaC1yc2EAAAADAQABAAABAQChxclCCpzzSqjbocO5s5/Pm0XFWDqxenuA
XEDxxBz2Y8kKeIZeaf6YKMWBYUM+SFBNH8Y5VkHoBPggTWohKe/Yxwwj/abhEZzZ
pSEzhGUm2xii4Qwc/MRyGNe6d99caXJJy+CJQztMkJdzwpY3r384HBmdy+SRmW2S
+Isz0FOMfF+eIZf63ifU3RQKldTKl+vzOlugRj0AROxkF3bvRDwhpCYwuCrtK+hC
rSdRoVcgQVp97lvXbl5GM+bCBg/TNGP05dIs2eZoFPeVgh74TCU53yab7RPVmgEj
oXMGx/pLBtmua6uYsQXt2tLnnPIwaTOI+NLRrycTa89xM2jU3Vv/
Private-Lines: 14
AAABAQCOY1xluJm0ur4tsxBnX2cGgJDExofCtyAFNy4ino8vf1zwzmzWpUzl+Nz+
p/Fb3KJxf8olpXqVEeqj4//J+POXRnu1IgnEiJAaMXIruhiePrJMivDygrkWBC+9
fM0otddWhRC5QGftWEc2KMu3b8z2QiV58oDYdscvWXyMuo0PVPJhjgHcTZVMbpYW
ISWckZQUMQRV/rAZVAegLDYsQP212KogFPQlzaHJRFIvxf6OZkE7bvvIMSARXEGu
OeKru38n34vk7Tp7f6+f8KtGYCkyjYyhImThfA1ne/SjEM9CRIf+AH2jhKyB+C8D
o4tsf5DVnC6orbdnt4bT0gwjaeihAAAAgQDaY5BCPLD+w3Q8TRZbGw73AsA8tPss
1Qv5p044iFXu2PkL/YtaMrMYwRn9IqasjvM0BJlNJDfEmUu67jsa+nWgaKlVWmYz
Em4WYK8CFkWr5wZLUqztemKYfgKT7vEmPLQun3HS9P7+AyyiX71YBEXucJu7HsIc
I46tTza842XtUwAAAIEAvaIYUqlbHOqxdFyqMAH6daH5KzCneF9S3JmVt6U52GAE
8d1Cj3XRRSKTPPt66dDaewlVqhqPjcnSxET/n0+VnrKal2UBrslwFWF8szpX6+Zo
B3n3Upg1MdlTaFrmPpJGDehT9NjerUOLFvgEvkwdCHedoyLeIXm6zsFJ3/Mk1SUA
AACBAMgeyHq/4Nur+/DY4i5IrlQUX6gpQF2hb1xj8WElaBQa+4IgHWeApDAycIc1
D1pLXKHClacSpKqv/6gHlz4KkGsnRUe3bpm+fP0XjIjTPp4l4s32TCqY9X3Eu5fL
UaRqrMtlJ19TMD8rgD1GkVVzBOJXsUHUwTcCg0JhY1DNuC4Y
Private-MAC: 1e430a894b1ac27e8e67f633c823792c078574ed

22
terraform/.terraform.lock.hcl generated Normal file
View File

@@ -0,0 +1,22 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/aws" {
version = "4.32.0"
constraints = "~> 4.16"
hashes = [
"h1:CmNkbcfctajxal8fnFFWLSC5dDvQwSJrw7HiwpTdyUc=",
"zh:062c30cd8bcf29f8ee34c2b2509e4e8695c2bcac8b7a8145e1c72e83d4e68b13",
"zh:1503fabaace96a7eea4d73ced36a02a75ec587760850e58162e7eff419dcbb31",
"zh:39a1fa36f8cb999f048bf0000d9dab40b8b0c77df35584fb08aa8bd6c5052dee",
"zh:471a755d43b51cd7be3e386cebc151ad8d548c5dea798343620476887e721882",
"zh:61ed56fab811e62b8286e606d003f7eeb7e940ef99bb49c1d283d91c0b748cc7",
"zh:80607dfe5f7770d136d5c451308b9861084ffad08139de8014e48672ec43ea3f",
"zh:863bf0a6576f7a969a89631525250d947fbb207d3d13e7ca4f74d86bd97cdda3",
"zh:9a8f2e77e4f99dbb618eb8ad17218a4698833754b50d46da5727323a2050a400",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:9b74ff6e638c2a470b3599d57c2081e0095976da0a54b6590884d571f930b53b",
"zh:da4fc553d50ae833d860ec95120e271c29b4cb636917ab5991327362b7486bb7",
"zh:f4b86e7df4e846a38774e8e648b41c5ebaddcefa913cfa1864568086b7735575",
]
}

64
terraform/appServer.tf Normal file
View File

@@ -0,0 +1,64 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "app_server" {
ami = var.ami_id
instance_type = "t2.micro"
key_name = var.ami_key_pair_name
security_groups = ["${aws_security_group.ingress-all-test.id}"]
# this is probably the only way to get the remote-execution (below) working. The elastic IP is not avaialable at this time
associate_public_ip_address = true
tags = {
"Name" = var.ami_name
}
subnet_id = "${aws_subnet.subnet-uno.id}"
connection {
type="ssh"
user="ubuntu"
host = self.public_ip
# we are assuming the ppk key is loaded into pageant...
agent = true
}
# Upload the set up script
provisioner "file" {
source = "setupAppServer.sh"
destination = "/tmp/setupAppServer.sh"
}
# Uplaod docker image
provisioner "file" {
source = "../docker/dumbserver.image.tar"
destination = "/tmp/dumbserver.image.tar"
}
# Upload example data file
provisioner "file" {
source = "../app/dataDir/data"
destination = "/tmp/data"
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/setupAppServer.sh",
"sudo /tmp/setupAppServer.sh"
]
}
}

7
terraform/gateways.tf Normal file
View File

@@ -0,0 +1,7 @@
resource "aws_internet_gateway" "test-env-gw" {
tags = {
"Name" = "tf-gateway-test-env"
}
vpc_id = "${aws_vpc.test-env.id}"
}

18
terraform/network.tf Normal file
View File

@@ -0,0 +1,18 @@
resource "aws_vpc" "test-env" {
tags = {
"Name" = "tf-vpc-test-env"
}
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
}
resource "aws_eip" "ip-test-env" {
tags = {
"Name" = "tf-EIP-IP-test-env"
}
instance = "${aws_instance.app_server.id}"
vpc = true
}

9
terraform/outputs.tf Normal file
View File

@@ -0,0 +1,9 @@
output "instance_public_ip" {
description = "Public IP address of the EC2 instance"
value = aws_instance.app_server.public_ip
}
output "elastic_ip" {
description = "ELASTIC IP"
value = aws_eip.ip-test-env.public_ip
}

30
terraform/security.tf Normal file
View File

@@ -0,0 +1,30 @@
resource "aws_security_group" "ingress-all-test" {
name = "allow-all-sg"
tags = {
"Name" = "tf-allow-all-sg"
}
vpc_id = "${aws_vpc.test-env.id}"
ingress {
cidr_blocks = [
"0.0.0.0/0"
]
from_port = 22
to_port = 22
protocol = "tcp"
}
ingress {
cidr_blocks = [
"0.0.0.0/0"
]
from_port = 1280
to_port = 1280
protocol = "tcp"
}
// Terraform removes the default rule
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

View File

@@ -0,0 +1,25 @@
#!/bin/bash
export DEBIAN_FRONTEND=noninteractive
apt -y update
apt -y upgrade
apt -y update
apt -y install podman
podman image load -i /tmp/dumbserver.image.tar
# create the directory for the data file and, if not existing (which is the default) copy the example file
mkdir -p /var/local/dumbserver
if [ ! -f /var/local/dumbserver/data ]; then
cp /tmp/data /var/local/dumbserver/
fi
podman run --name dumbserver -d -p 1280:1280 -v /var/local/dumbserver:/nodejsapp/dataDir dumbserver
# make sure it comes up after reboot...
podman generate systemd --new --name dumbserver > /etc/systemd/system/dumbserver-podman.service
systemctl daemon-reload
systemctl enable dumbserver-podman.service
# finally, all is set up and after all the updates we want to reboot into the new kernel version
shutdown -r 1

25
terraform/subnets.tf Normal file
View File

@@ -0,0 +1,25 @@
resource "aws_subnet" "subnet-uno" {
tags = {
"Name" = "tf-subnet-uno"
}
cidr_block = "${cidrsubnet(aws_vpc.test-env.cidr_block, 3, 1)}"
vpc_id = "${aws_vpc.test-env.id}"
availability_zone = "us-west-2a"
}
resource "aws_route_table" "route-table-test-env" {
tags = {
"Name" = "tf-route-table-test-env"
}
vpc_id = "${aws_vpc.test-env.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.test-env-gw.id}"
}
}
resource "aws_route_table_association" "subnet-association" {
subnet_id = "${aws_subnet.subnet-uno.id}"
route_table_id = "${aws_route_table.route-table-test-env.id}"
}

13
terraform/variables.tf Normal file
View File

@@ -0,0 +1,13 @@
variable "ami_id" {
type = string
default = "ami-017fecd1353bcc96e"
}
variable "ami_key_pair_name" {
type=string
default = "teraformtest1"
}
variable "ami_name" {
type = string
default = "dumbApplicationServer"
}