Iperf - 1000BASE-LX SMF LC/LC Fiber Link Speed Test 
HOST A - SERVER

angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$ date
Sun Mar 3 02:04:35 PM PST 2024

#IPv4
angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$ iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
[ 1] local 192.168.1.184 port 5001 connected with 192.168.1.192 port 57642 (icwnd/mss/irtt=14/1448/515)
[ ID] Interval Transfer Bandwidth
[ 1] 0.00-10.01 sec 1.10 GBytes 941 Mbits/sec
angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$
angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$

# IPv6
angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$ iperf -s -V
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
[ 1] local 2603:8000:6a00:5748:xxxx:xxxx:xxxx:xxxx port 5001 connected with 2603:8000:6a00:5748:xxxx:xxxx:xxxx:xxxx port 56868 (icwnd/mss/irtt=13/1428/460)
[ ID] Interval Transfer Bandwidth
[ 1] 0.00-10.02 sec 1.08 GBytes 928 Mbits/sec
angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$


HOST B - CLIENT

acool@localhost ~]$
# IPv4
[acool@localhost ~]$ iperf -c 192.168.1.184
------------------------------------------------------------
Client connecting to 192.168.1.184, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[ 1] local 192.168.1.192 port 57642 connected with 192.168.1.184 port 5001 (icwnd/mss/irtt=14/1448/731)
[ ID] Interval Transfer Bandwidth
[ 1] 0.00-10.02 sec 1.10 GBytes 940 Mbits/sec

# IPv6
[acool@localhost ~]$ iperf -c 2603:8000:6a00:xxxx:xxxx:xxxx:xxxx
------------------------------------------------------------
Client connecting to 2603:8000:6a00:xxxx:xxxx:xxxx:xxxx, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[ 1] local 2603:8000:6a00:5748:: port 56868 connected with 2603:8000:6a00:5748:xxxx:xxxx:xxxx:xxxx port 5001 (icwnd/mss/irtt=13/1428/783)
[ ID] Interval Transfer Bandwidth
[ 1] 0.00-10.02 sec 1.08 GBytes 928 Mbits/sec
[acool@localhost ~]$


[ view entry ] ( 58 views )   |  print article
SSL/TLS: Wildcard certificate 
Tested and working on 11/15/2023 !

# Create root CA
[acool@localhost tls]$openssl req --x509 --nodes --days 3650 --newkey rsa:2048 --keyout ENT-CA.key --out ENT-CA.crt

# Crate new key and signing request (Tip: remove --aes256 to remove passphrase requirement... I think)
Passphrase: mypassphrase
[acool@localhost tls]$openssl genrsa --out star-dev-localhost.key --aes256 2048
[acool@localhost tls]$openssl req --new --key star-dev-localhost.key --out star-dev-localhost.csr

# Sign request
[acool@localhost tls]$openssl x509 --req --in star-dev-localhost.csr --CA ENT-CA.crt --CAkey ENT-CA.key --CAcreateserial --days 3650 --sha256 --extfile star-dev-localhost.cnf --out star-dev-localhost.crt

# remove passphrase
[acool@localhost tls]$openssl rsa --in star-dev-localhost.key --out star-dev-localhost-nopassphrase.key

[acool@localhost tls]$ cat star-dev-localhost.cnf
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.dev.localhost
[acool@localhost tls]$
[acool@localhost tls]


# finally, import ENT-CA.crt certificate in Chrome
# chrome://settings/certificates


Configure Nginx:
...
listen 443 ssl;
ssl_certificate /etc/ssl/certs/star-dev-localhost.crt;
ssl_certificate_key /etc/ssl/certs/star-dev-localhost-nopassphrase.key;
...


[ view entry ] ( 158 views )   |  print article
C 101: Foreach loop macro 
[acool@localhost ~]$ 
[acool@localhost ~]$ date
Mon Apr 3 11:17:50 AM PDT 2023
[acool@localhost ~]$
[acool@localhost ~]$ cat c-foreach-macro.c
#include <stdio.h>

#define foreach(item, array) \
for(int keep = 1, \
count = 0,\
size = sizeof (array) / sizeof *(array); \
keep && count != size; \
keep = !keep, count++) \
for(item = (array) + count; keep; keep = !keep)

int main()
{
int mynumbers[] = {5,20,35,62,8,74,89};

char mygreeting[] = {"Hello world!"};

float myfloats[] = {1.6,6.9,5.8,43.5,1.1,0.9};

foreach(int *v, mynumbers) {
printf("value: %d\n", *v);
}

foreach(char *v, mygreeting) {
printf("value: %c\n", *v);
}

foreach(float *v, myfloats) {
printf("value: %.2f\n", *v);
}

return 0;
}
[acool@localhost ~]$
[acool@localhost ~]$ gcc c-foreach-macro.c -o c-foreach-macro
[acool@localhost ~]$
[acool@localhost ~]$ ./c-foreach-macro
value: 5
value: 20
value: 35
value: 62
value: 8
value: 74
value: 89
value: H
value: e
value: l
value: l
value: o
value:
value: w
value: o
value: r
value: l
value: d
value: !
value:
value: 1.60
value: 6.90
value: 5.80
value: 43.50
value: 1.10
value: 0.90
[acool@localhost ~]$


Bonus - dumping output from preprocessor.
[acool@localhost ~]$ 
[acool@localhost ~]$ gcc c-foreach-macro.c -E -o c-macro.preprocessed
[acool@localhost ~]$
[acool@localhost ~]$ cat c-macro.preprocessed
...
int main()
{
int mynumbers[] = {5,20,35,62,8,74,89};

char mygreeting[] = {"Hello world!"};

float myfloats[] = {1.6,6.9,5.8,43.5,1.1,0.9};

for(int keep = 1, count = 0, size = sizeof (mynumbers) / sizeof *(mynumbers); keep && count != size; keep = !keep, count++) for(int *v = (mynumbers) + count; keep; keep = !keep) {
printf("value: %d\n", *v);
}

for(int keep = 1, count = 0, size = sizeof (mygreeting) / sizeof *(mygreeting); keep && count != size; keep = !keep, count++) for(char *v = (mygreeting) + count; keep; keep = !keep) {
printf("value: %c\n", *v);
}

for(int keep = 1, count = 0, size = sizeof (myfloats) / sizeof *(myfloats); keep && count != size; keep = !keep, count++) for(float *v = (myfloats) + count; keep; keep = !keep) {
printf("value: %.2f\n", *v);
}

return 0;
}
[acool@localhost ~]$


[ view entry ] ( 196 views )   |  print article
C 101: Creating Child Processes With A Loop 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

void child( int seconds );

int children = 15;

int main(void)
{
printf("Parent ID %d, Main ID %d \n", getppid(), getpid());

for(int i=0;i<children;i++)
{
if(fork()==0)
{
child(children-i); // pass seconds to sleep
}
else
{
wait(NULL);
}
}
}

void child(int seconds)
{
printf("Parent ID %d, Child ID %d, Sleeping %d seconds.\n", getppid(), getpid(), seconds);
sleep(seconds);
exit(0);
}

[acool@localhost C-Exercises]$ date
Sun Oct 23 04:14:24 PM PDT 2022
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ gcc parent_children.c
[acool@localhost C-Exercises]$ ./a.out
Parent ID 4298, Main ID 10357
Parent ID 10357, Child ID 10358, Sleeping 15 seconds.
Parent ID 10357, Child ID 10394, Sleeping 14 seconds.
Parent ID 10357, Child ID 10436, Sleeping 13 seconds.
Parent ID 10357, Child ID 10475, Sleeping 12 seconds.
Parent ID 10357, Child ID 10510, Sleeping 11 seconds.
Parent ID 10357, Child ID 10532, Sleeping 10 seconds.
Parent ID 10357, Child ID 10546, Sleeping 9 seconds.
Parent ID 10357, Child ID 10558, Sleeping 8 seconds.
Parent ID 10357, Child ID 10581, Sleeping 7 seconds.
Parent ID 10357, Child ID 10598, Sleeping 6 seconds.
Parent ID 10357, Child ID 10607, Sleeping 5 seconds.
Parent ID 10357, Child ID 10613, Sleeping 4 seconds.
Parent ID 10357, Child ID 10647, Sleeping 3 seconds.
Parent ID 10357, Child ID 10732, Sleeping 2 seconds.
Parent ID 10357, Child ID 10815, Sleeping 1 seconds.
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ ps -A |grep a.out
10357 pts/0 00:00:00 a.out
10394 pts/0 00:00:00 a.out
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ pstree -p 10357
a.out(10357)───a.out(10436)
[acool@localhost C-Exercises]$

Slightly different version, in this version we don't wait() for each child individually.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

void child( int seconds );

int children = 15;

int main(void)
{
printf("Parent ID %d, Main ID %d \n", getppid(), getpid());

for(int i=0;i<children;i++)
{
if(fork()==0)
{
child(children-i); // pass seconds to sleep
}
}

while (wait(NULL) > 0); // wait for all children to finish
}

void child(int seconds)
{
printf("Parent ID %d, Child ID %d, Sleeping %d seconds.\n", getppid(), getpid(), seconds);
sleep(seconds);
exit(0);
}

[acool@localhost C-Exercises]$ 
[acool@localhost C-Exercises]$ gcc parent_children.c
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ ./a.out
Parent ID 4298, Main ID 14322
Parent ID 14322, Child ID 14323, Sleeping 15 seconds.
Parent ID 14322, Child ID 14324, Sleeping 14 seconds.
Parent ID 14322, Child ID 14325, Sleeping 13 seconds.
Parent ID 14322, Child ID 14326, Sleeping 12 seconds.
Parent ID 14322, Child ID 14327, Sleeping 11 seconds.
Parent ID 14322, Child ID 14328, Sleeping 10 seconds.
Parent ID 14322, Child ID 14329, Sleeping 9 seconds.
Parent ID 14322, Child ID 14330, Sleeping 8 seconds.
Parent ID 14322, Child ID 14331, Sleeping 7 seconds.
Parent ID 14322, Child ID 14332, Sleeping 6 seconds.
Parent ID 14322, Child ID 14333, Sleeping 5 seconds.
Parent ID 14322, Child ID 14334, Sleeping 4 seconds.
Parent ID 14322, Child ID 14335, Sleeping 3 seconds.
Parent ID 14322, Child ID 14336, Sleeping 2 seconds.
Parent ID 14322, Child ID 14337, Sleeping 1 seconds.
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ pstree -p 14322
a.out(14322)─┬─a.out(14323)
├─a.out(14324)
├─a.out(14325)
├─a.out(14326)
├─a.out(14327)
├─a.out(14328)
├─a.out(14329)
├─a.out(14330)
├─a.out(14331)
├─a.out(14332)
├─a.out(14333)
├─a.out(14334)
└─a.out(14335)
[acool@localhost C-Exercises]$ ps -A |grep a.out
14322 pts/0 00:00:00 a.out
14323 pts/0 00:00:00 a.out
14324 pts/0 00:00:00 a.out
14325 pts/0 00:00:00 a.out
14326 pts/0 00:00:00 a.out
14327 pts/0 00:00:00 a.out
14328 pts/0 00:00:00 a.out
14329 pts/0 00:00:00 a.out
14330 pts/0 00:00:00 a.out
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ pstree -p 14322
a.out(14322)─┬─a.out(14323)
├─a.out(14324)
├─a.out(14325)
├─a.out(14326)
├─a.out(14327)
└─a.out(14328)
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$


[ view entry ] ( 232 views )   |  print article
C101: Printing Emojis 
#include <stdio.h>
#include <wchar.h>
#include <locale.h>

// multibyte array, each character is 4 bytes long
wchar_t mystring[] = L"Angel Cool á 🤪 😁 ა";

// [acool@localhost other]$ gcc -Wall -ggdb emoji-multibyte-array.c -o emoji-multibyte-array
int main()
{
setlocale(LC_ALL,"");

// print total number of characters in string
wprintf(L"wcslen of wchar_t mystring[]: %ld\n", wcslen(mystring));

// output string
wprintf(L"%ls\n",mystring);

// print one character
wprintf(L"Emoji : %lc\n", mystring[13]);

// print all
for (int j = 0; j < wcslen(mystring); ++j)
{
wprintf(L"%lc,", mystring[j]);
}

wprintf(L"\n");

// size in bytes of string, it also includes 4 bytes for the null (\0) characters at the end it seems
wprintf(L"Size in bytes of mystring[]: %d\n", sizeof(mystring));

// print size of wchar_t data type
wprintf(L"wchar_t is %d bytes long!\n", sizeof(wchar_t));

return 0;
}

[acool@localhost other]$ date
Sat Oct 22 12:05:24 PM PDT 2022
[acool@localhost other]$ gcc emoji-multibyte-array.c
[acool@localhost other]$ ./a.out
wcslen of wchar_t mystring[]: 18
Angel Cool á 🤪 😁 ა
Emoji : 🤪
A,n,g,e,l, ,C,o,o,l, ,á, ,🤪, ,😁, ,ა,
Size in bytes of mystring[]: 76
wchar_t is 4 bytes long!
[acool@localhost other]$


[ view entry ] ( 205 views )   |  print article
C 101: Preventing Zombie Processes  
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
pid_t pid;
int status;

pid = fork();

if(pid<0)
{
printf("Error: fork() returned %u.\n", pid);
return 1;
}

if(pid == 0)
{
printf("Child: PID is %u. Parent's PID is %u\n", getpid(), getppid());
sleep(10);
puts("Child: about to exit.\n");
return 33;
}
else
{
printf("Parent: PID is %u. Child's PID is %u\n", getpid(), pid);

while((pid=waitpid(-1,&status,WNOHANG)) == 0)
{
printf("Parent: No child has terminated.");
printf("Parent: Going to sleep for 1 second.\n");
sleep(1);
}
}

printf("Parent: child with PID %u ", pid);

if(WIFEXITED(status)!=0)
{
printf("exited with status %u\n",WIFEXITED(status));
}
else
{
printf("exited abnormally\n");
}

return 0;
}

Preventing Zombie Processes Using waitpid()
Listing 19.5 -Teach Yourself C For Linux Programming
[acool@localhost C-practice]$ gcc -Wall fork.c
[acool@localhost C-practice]$
[acool@localhost C-practice]$ ./a.out
Parent: PID is 57544. Child's PID is 57545
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Child: PID is 57545. Parent's PID is 57544
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Child: about to exit.

Parent: child with PID 57545 exited with status 1
[acool@localhost C-practice]$
[acool@localhost C-practice]$


[ view entry ] ( 236 views )   |  print article
C 101: Creating Structures 
Method 1:
// define it as a template
struct person {
char first_name[50];
char last_name[50];
};

// create two instances of person
struct person Person1, Person2;

// assign values to Person1
strcpy(Person1.first_name, "Angel");
strcpy(Person1.last_name, "Cool");

Method 2:
// define it and create two instances of it
struct car {
char make[50];
char color[50];
} Car1, Car2;

// assign values to Car1
strcpy(Car1.make, "Chevy");
strcpy(Car1.color, "red");

Method 3:
// use 'typedef' to create it
typedef struct {
char first_name[50];
char last_name[50];
} person;

// create two instances of person (no 'struct' keyword needed)
person Person1, Person2;

Method 1 example
[acool@localhost C-practice]$ 
[acool@localhost C-practice]$ cat method_1.c
#include <stdio.h>
#include <string.h>

void main(){
struct person {
char first_name[50];
char last_name[50];
};

// create two instances of person
struct person Person1, Person2;

// assign values to Person1
strcpy(Person1.first_name, "Angel");
strcpy(Person1.last_name, "Cool");

// print assigned values
printf("Hello %s %s!\n", Person1.first_name, Person1.last_name);
}
[acool@localhost C-practice]$ gcc method_1.c -o method_1
[acool@localhost C-practice]$ ./method_1
Hello Angel Cool!
[acool@localhost C-practice]$

Method 2 example
[acool@localhost C-practice]$ 
[acool@localhost C-practice]$ cat method_2.c
#include <stdio.h>
#include <string.h>

void main(){
// define it and create two instances of it
struct car {
char make[50];
char color[50];
} Car1, Car2;

// assign values to Car1
strcpy(Car1.make, "Chevy");
strcpy(Car1.color, "red");

// print assigned values
printf("My %s %s.\n",Car1.color, Car1.make);
}
[acool@localhost C-practice]$
[acool@localhost C-practice]$ gcc method_2.c -o method_2
[acool@localhost C-practice]$ ./method_2
My red Chevy.
[acool@localhost C-practice]$

Method 3 example
[acool@localhost C-practice]$ 
[acool@localhost C-practice]$ cat method_3.c
#include <stdio.h>
#include <string.h>

void main(){
// use 'typedef' to create it
typedef struct {
char first_name[50];
char last_name[50];
} person;

// create two instances of person (no 'struct' keyword needed)
person Person1, Person2;

// assign values to Person1
strcpy(Person1.first_name, "Andres Manuel");
strcpy(Person1.last_name, "Lopez-Obrador");

printf("Viva la 4T! Viva %s %s!\n", Person1.first_name, Person1.last_name);
}
[acool@localhost C-practice]$
[acool@localhost C-practice]$ gcc method_3.c -o method_3
[acool@localhost C-practice]$ ./method_3
Viva la 4T! Viva Andres Manuel Lopez-Obrador!
[acool@localhost C-practice]$
[acool@localhost C-practice]$


Another example:
[acool@localhost ~]$ 
[acool@localhost ~]$
[acool@localhost ~]$ date
Wed Apr 5 02:18:30 PM PDT 2023
[acool@localhost ~]$
[acool@localhost ~]$ cat books.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Books {
char title[50];
char author[50];
char subject[100];
int id;
};

typedef struct {
char title[50];
char author[50];
char subject[100];
int id;
} eBooks;

void printdetails(eBooks *myEbook, struct Books *myBook)
{
printf( "myBook id : %d\n", myBook->id);
printf( "myBook title : %s\n", myBook->title);
printf( "myBook author : %s\n", myBook->author);
printf( "myBook subject : %s\n", myBook->subject);

printf("====================================\n");

printf( "myEbook id : %d\n", myEbook->id);
printf( "myEbook title : %s\n", myEbook->title);
printf( "myEbook author : %s\n", myEbook->author);
printf( "myEbook subject : %s\n", myEbook->subject);
}

int main()
{
// Pay attention to this! ...two different ways to declare it.
struct Books *myBook = (struct Books *) malloc(sizeof(struct Books));
eBooks *myEbook = (eBooks *) malloc(sizeof(eBooks));

strcpy( myBook->title, "C Programming");
strcpy( myBook->author, "Angel Cool");
strcpy( myBook->subject, "Programming C Structs Examples");
myBook->id = 1;

strcpy( myEbook->title, "C Programming (eBook)");
strcpy( myEbook->author, "Angel Cool (eBook)");
strcpy( myEbook->subject, "Programming C Structs Examples (eBook)");
myEbook->id = 2;

printdetails(myEbook,myBook);

return 0;
}
[acool@localhost ~]$
[acool@localhost ~]$
[acool@localhost ~]$ gcc books.c -o books
[acool@localhost ~]$
[acool@localhost ~]$ ./books
myBook id : 1
myBook title : C Programming
myBook author : Angel Cool
myBook subject : Programming C Structs Examples
====================================
myEbook id : 2
myEbook title : C Programming (eBook)
myEbook author : Angel Cool (eBook)
myEbook subject : Programming C Structs Examples (eBook)
[acool@localhost ~]$
[acool@localhost ~]$ file books
books: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ea1090588d4c761da3060066a7d7a67b7db9caa6, for GNU/Linux 3.2.0, not stripped
[acool@localhost ~]$
[acool@localhost ~]$


[ view entry ] ( 232 views )   |  print article
Terraform: AWS VPC with IPV6 support 
[acool@localhost EC2-VPC]$ 
[acool@localhost EC2-VPC]$ date
Sun Jul 4 06:19:34 PM PDT 2021
[acool@localhost EC2-VPC]$ cat /etc/redhat-release
Fedora release 33 (Thirty Three)
[acool@localhost EC2-VPC]$ aws --version
aws-cli/1.18.223 Python/3.9.5 Linux/5.12.13-200.fc33.x86_64 botocore/1.19.63
[acool@localhost EC2-VPC]$ terraform -v
Terraform v1.0.1
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v3.48.0
[acool@localhost EC2-VPC]$

The gist of this post:
 
[acool@localhost EC2-VPC]$
[acool@localhost EC2-VPC]$ cat main.tf
# extract public ssh key from private ssh key
# [acool@localhost EC2-VPC]$ ssh-keygen -y -f ./COOL_SSH_PRIVATEKEY.pem > COOL_SSH_PUBLICKEY.pub

// a.- set region to use
provider "aws" {
region = "us-east-2"
}

// b.- create ssh key pair
resource "aws_key_pair" "COOL_KEY_PAIR" {
key_name = "COOL_SSH_KEYPAIR"
public_key = "${file("./COOL_SSH_PUBLICKEY.pub")}"
}

// c.- create vpc resource
resource "aws_vpc" "COOL_VPC" {
enable_dns_support = true
enable_dns_hostnames = true
assign_generated_ipv6_cidr_block = true
cidr_block = "10.0.0.0/16"
}

// d.- create subnet
resource "aws_subnet" "COOL_VPC_SUBNET" {
vpc_id = "${aws_vpc.COOL_VPC.id}"
cidr_block = "${cidrsubnet(aws_vpc.COOL_VPC.cidr_block, 4, 1)}"
map_public_ip_on_launch = true

ipv6_cidr_block = "${cidrsubnet(aws_vpc.COOL_VPC.ipv6_cidr_block, 8, 1)}"
assign_ipv6_address_on_creation = true
}

// e.- create internet gateway
resource "aws_internet_gateway" "COOL_GATEWAY" {
vpc_id = "${aws_vpc.COOL_VPC.id}"
}

// f.- create routing table
resource "aws_default_route_table" "COOL_VPC_ROUTING_TABLE" {
default_route_table_id = "${aws_vpc.COOL_VPC.default_route_table_id}"

route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.COOL_GATEWAY.id}"
}

route {
ipv6_cidr_block = "::/0"
gateway_id = "${aws_internet_gateway.COOL_GATEWAY.id}"
}
}

// g.- create some sort of association needed
resource "aws_route_table_association" "COOL_SUBNET_ROUTE_TABLE_ASSOCIATION" {
subnet_id = "${aws_subnet.COOL_VPC_SUBNET.id}"
route_table_id = "${aws_default_route_table.COOL_VPC_ROUTING_TABLE.id}"
}

// h.- create security group
resource "aws_security_group" "COOL_SECURITY_GROUP" {
name = "COOL_SECURITY_GROUP"
vpc_id = "${aws_vpc.COOL_VPC.id}"

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
ipv6_cidr_blocks = ["::/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmpv6"
ipv6_cidr_blocks = ["::/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
ipv6_cidr_blocks = ["::/0"]
}
}

// i.- create EC2 instance
resource "aws_instance" "COOL_INSTANCE_APP01" {
ami = "ami-01d5ac8f5f8804300"
key_name = "COOL_SSH_KEYPAIR"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.COOL_VPC_SUBNET.id}"
ipv6_address_count = 1
vpc_security_group_ids = ["${aws_security_group.COOL_SECURITY_GROUP.id}"]

tags = {
Name = "COOL_INSTANCE_APP01"
}

depends_on = [aws_internet_gateway.COOL_GATEWAY]
}

//j.- print instance IPs
output "COOL_INSTANCE_APP01_IPv4" {
value = "${aws_instance.COOL_INSTANCE_APP01.public_ip}"
}

output "COOL_INSTANCE_APP01_IPv6" {
value = ["${aws_instance.COOL_INSTANCE_APP01.ipv6_addresses}"]
}
[acool@localhost EC2-VPC]$
[acool@localhost EC2-VPC]$ terraform init
...
[acool@localhost EC2-VPC]$
[acool@localhost EC2-VPC]$ terraform apply
...
[acool@localhost EC2-VPC]$


Happy 4th of July, 2021! and cheers!


UPDATE - November 9, 2021
Added 'app_servers' variable to create multiple aws_instances.
Commit message: 'Added EIP and specified private ip addresses.'

main.tf :

# extract public ssh key from private ssh key
# [acool@localhost EC2-VPC]$ ssh-keygen -y -f ./COOL_SSH_PRIVATEKEY.pem > COOL_SSH_PUBLICKEY.pub

// set region to use
provider "aws" {
region = "us-east-2"
}

// create ssh key pair
resource "aws_key_pair" "COOL_KEY_PAIR" {
key_name = "COOL_SSH_KEYPAIR"
public_key = "${file("./COOL_SSH_PUBLICKEY.pub")}"
}

// create vpc resource
resource "aws_vpc" "COOL_VPC" {
enable_dns_support = true
enable_dns_hostnames = true
assign_generated_ipv6_cidr_block = true
cidr_block = "10.0.0.0/16"
}

// create subnet
resource "aws_subnet" "COOL_PVC_SUBNET" {
vpc_id = "${aws_vpc.COOL_VPC.id}"
cidr_block = "${cidrsubnet(aws_vpc.COOL_VPC.cidr_block, 4, 1)}"
map_public_ip_on_launch = true

ipv6_cidr_block = "${cidrsubnet(aws_vpc.COOL_VPC.ipv6_cidr_block, 8, 1)}"
assign_ipv6_address_on_creation = true
}

// create internet gateway
resource "aws_internet_gateway" "COOL_GATEWAY" {
vpc_id = "${aws_vpc.COOL_VPC.id}"
}

// create routing table
resource "aws_default_route_table" "COOL_VPC_ROUTING_TABLE" {
default_route_table_id = "${aws_vpc.COOL_VPC.default_route_table_id}"

route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.COOL_GATEWAY.id}"
}

route {
ipv6_cidr_block = "::/0"
gateway_id = "${aws_internet_gateway.COOL_GATEWAY.id}"
}
}

// create some sort of association needed
resource "aws_route_table_association" "COOL_SUBNET_ROUTE_TABLE_ASSOCIATION" {
subnet_id = "${aws_subnet.COOL_PVC_SUBNET.id}"
route_table_id = "${aws_default_route_table.COOL_VPC_ROUTING_TABLE.id}"
}

// create security group
resource "aws_security_group" "COOL_SECURITY_GROUP" {
name = "COOL_SECURITY_GROUP"
vpc_id = "${aws_vpc.COOL_VPC.id}"

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
ipv6_cidr_blocks = ["::/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmpv6"
ipv6_cidr_blocks = ["::/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
ipv6_cidr_blocks = ["::/0"]
}
}

// server names
variable app_servers {
description = "name of app servers"
type = list(map(any))
default = [
{name:"COOL_LB01", ip:"10.0.16.4"},
{name:"COOL_LB02", ip:"10.0.16.5"},
{name:"COOL_APP01", ip:"10.0.16.6"},
{name:"COOL_APP02", ip:"10.0.16.7"},
]
}

// create EC2 instance
resource "aws_instance" "COOL_SERVERS" {
ami = "ami-01d5ac8f5f8804300"
key_name = "COOL_SSH_KEYPAIR"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.COOL_PVC_SUBNET.id}"
ipv6_address_count = 1
vpc_security_group_ids = ["${aws_security_group.COOL_SECURITY_GROUP.id}"]
for_each = {for server in var.app_servers: server.name => server}
private_ip = each.value["ip"]

tags = {
Name = each.value["name"]
}

depends_on = [aws_internet_gateway.COOL_GATEWAY]
}

// elastic IP
resource "aws_eip" "COOL_EIP" {
instance = aws_instance.COOL_SERVERS["COOL_LB01"].id
vpc = true
}

// print instance IPs
output "COOL_INSTANCE_APP01_IPv4" {
value = {for k, v in aws_instance.COOL_SERVERS: k => v.public_ip}
}

output "COOL_INSTANCE_APP01_IPv6" {
value = {for k, v in aws_instance.COOL_SERVERS: k => v.ipv6_addresses}
}

output "COOL_VPC_IPV6_BLOCK" {
value = aws_subnet.COOL_PVC_SUBNET.ipv6_cidr_block
}

// SSH to instance:
// [acool@localhost EC2-VPC]$ ssh -i ./COOL_SSH_PRIVATEKEY.pem centos@ip_address

// remove eip from COOL_LB01
// [acool@localhost EC2-VPC]$ aws ec2 disassociate-address --region us-east-2 --public-ip 3.131.249.150

// assign eip to COOL_LB02, adjust instance id to match LB02. The same commands work to return eip to LB01
// [acool@localhost EC2-VPC]$ aws ec2 associate-address --region us-east-2 --public-ip 3.131.249.150 --instance-id i-05a634252654b7b34



[ view entry ] ( 480 views )   |  print article
Terraform: AWS EC2 single instance example. 
[acool@localhost terraform-tests]$ terraform --version
Terraform v1.0.1
...
[acool@localhost terraform-tests]$ aws --version
aws-cli/1.18.223 Python/3.9.5 Linux/5.12.12-200.fc33.x86_64 botocore/1.19.63
...

The gist of this post:
[acool@localhost EC2-SINGLE-INSTANCE]$ cat main.tf 
provider "aws" {
region = "us-east-2"
}

// create ssh key
resource "tls_private_key" "COOL_SSH_PK" {
algorithm = "RSA"
rsa_bits = 4096
}

// create ssh key pair
resource "aws_key_pair" "COOL_KEY_PAIR" {
key_name = "COOL_SSH_KEYNAME"
public_key = tls_private_key.COOL_SSH_PK.public_key_openssh

provisioner "local-exec" { # Create "myKey.pem" to your computer!!
command = "echo '${tls_private_key.COOL_SSH_PK.private_key_pem}' > ./COOL_SSH_PK.pem"
}
}

// create aws ec2 instance
resource "aws_instance" "COOLAPP01" {
ami = "ami-01d5ac8f5f8804300"
instance_type = "t2.micro"
key_name = aws_key_pair.COOL_KEY_PAIR.key_name
vpc_security_group_ids = [aws_security_group.COOLAPP01_security_group.id]

tags = {
Name = "COOLAPP01_tag_name"
}
}

// create security group
resource "aws_security_group" "COOLAPP01_security_group" {

name="terraform_COOLAPP01_security_group"

// allow port 80 tcp
ingress{
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow port 22 tcp
ingress{
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow all outbound traffic
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

// TODO: enable IPV6

output "public_ip" {
value = aws_instance.COOLAPP01.public_ip
description = "public ip for COOLAPP01"
}
[acool@localhost EC2-SINGLE-INSTANCE]$
[acool@localhost EC2-SINGLE-INSTANCE]$terraform apply
...


Happy 4th of July, 2021 ya'll!!

[ view entry ] ( 377 views )   |  print article
Highly Available HAproxy Balancer with Keepalived 
We're gonna use Keepalived's VRRP feature.

Floating ip address will be 192.168.121.179

Vagrantfile needed parameters:

config.vm.box = "centos/8"
config.vm.network "private_network", ip: "192.168.121.180"
config.vm.hostname = "lb01.localhost"

config.vm.box = "centos/8"
config.vm.network "private_network", ip: "192.168.121.181"
config.vm.hostname = "lb02.localhost"

config.vm.box = "centos/8"
config.vm.network "private_network", ip: "192.168.121.191"
config.vm.hostname = "app01.localhost"

config.vm.box = "centos/8"
config.vm.network "private_network", ip: "192.168.121.192"
config.vm.hostname = "app02.localhost"

------------------------------------------------------------------------
app01 and app02 will have nginx installed running its default welcome page.

angel@acool:~/Documents/haproxy-cluster$ date
Fri 21 May 2021 07:11:52 PM PDT
angel@acool:~/Documents/haproxy-cluster$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.2 LTS"
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster$ tree
.
├── app01
│   └── Vagrantfile
├── app02
│   └── Vagrantfile
├── lb01
│   └── Vagrantfile
├── lb02
│   └── Vagrantfile
└── NOTES.txt

4 directories, 5 files
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster$ sudo vagrant global-status
id name provider state directory
------------------------------------------------------------------------------
1553a24 default libvirt shutoff /home/angel/Documents/haproxy-cluster/lb01
3c33424 default libvirt shutoff /home/angel/Documents/haproxy-cluster/lb02
1d9af06 default libvirt shutoff /home/angel/Documents/haproxy-cluster/app01
5bc8220 default libvirt shutoff /home/angel/Documents/haproxy-cluster/app02
...
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster/lb01$ vagrant --version
Vagrant 2.2.6
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster$ cd lb01/
angel@acool:~/Documents/haproxy-cluster/lb01$ sudo vagrant up
...
angel@acool:~/Documents/haproxy-cluster/lb01$ sudo vagrant ssh
Last login: Sat May 22 02:08:45 2021 from 192.168.121.1
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ cat /etc/redhat-release
CentOS Linux release 8.3.2011
[vagrant@lb01 ~]$ sudo dnf install haproxy keepalived

[vagrant@lb01 ~]$ haproxy -v
HA-Proxy version 1.8.23 2019/11/25
Copyright 2000-2019 Willy Tarreau <willy@haproxy.org>

[vagrant@lb01 ~]$ keepalived --version
Keepalived v2.0.10 (11/12,2018)
...
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ cat /etc/sysctl.conf
...
net.ipv4.ip_nonlocal_bind=1
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ sudo sysctl -p
net.ipv4.ip_nonlocal_bind = 1
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ cat /etc/haproxy/haproxy.cfg
...
## enable stats
listen stats
bind :9000
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST

## enable www frontend, bind floating ip address
frontend www
bind 192.168.121.179:80
mode http
default_backend www_servers

## enable www backend
backend www_servers
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server app01 192.168.121.191:80 check
server app02 192.168.121.192:80 check

[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ cat /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy { # Requires keepalived-1.1.13
#script "killall -0 haproxy" # cheaper than pidof
script "pidof haproxy" # this one worked better for me.
interval 2 # check every 2 seconds
weight 2 # add 2 points of priority if OK
}
vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 51
priority 101 # 101 on lb01, 100 on lb02
virtual_ipaddress {
192.168.121.179
}
track_script {
chk_haproxy
}
}
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ # this should be the end result, the floating ip should be listed.
[vagrant@lb01 ~]$ ip a |grep 179
inet 192.168.121.179/32 scope global eth0
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ # if you stop haproxy (or shutdown lb01), lb02 should take over the floating ip!
[vagrant@lb01 ~]$ # when haproxy is back, lb01 will reclaim the floating ip, the end result is
[vagrant@lb01 ~]$ # the floating ip will be available even if lb01 goes down.


Cheers!

UPDATE: November 11, 2021 - Adding lb02 details in order to remove ambiguities when I see this post in the future.

[vagrant@lb02 ~]$ cat /etc/sysctl.conf
...
net.ipv4.ip_nonlocal_bind=1
[vagrant@lb02 ~]$


[vagrant@lb02 ~]$
[vagrant@lb02 ~]$
[vagrant@lb02 ~]$ cat /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy { # Requires keepalived-1.1.13
#script "killall -0 haproxy" # cheaper than pidof
script "pidof haproxy"
interval 2 # check every 2 seconds
weight 2 # add 2 points of priority if OK
}
vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 51
priority 100 # 101 on primary, 100 on secondary
virtual_ipaddress {
192.168.121.179
}
track_script {
chk_haproxy
}
}

[vagrant@lb02 ~]$


[vagrant@lb02 ~]$
[vagrant@lb02 ~]$
[vagrant@lb02 ~]$ cat /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# https://www.haproxy.org/download/1.8/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2

chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon

# turn on stats unix socket
stats socket /var/lib/haproxy/stats

# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000

# ME: enable stats
listen stats
bind :9000
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST

# ME:
frontend www
bind 192.168.121.179:80
mode http
default_backend www_servers

# ME:
backend www_servers
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server app01 192.168.121.191:80 check
server app02 192.168.121.192:80 check

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
bind *:5000
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js

use_backend static if url_static
default_backend app

#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
balance roundrobin
server static 127.0.0.1:4331 check

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
server app3 127.0.0.1:5003 check
server app4 127.0.0.1:5004 check
[vagrant@lb02 ~]$
[vagrant@lb02 ~]$





[ view entry ] ( 456 views )   |  print article

<Back | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Next> Last>>


2024 By Angel Cool