write post
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
position: static
|
||||
}
|
||||
|
||||
.m-1 {
|
||||
margin: 0.25rem
|
||||
.-mt-4 {
|
||||
margin-top: -1rem
|
||||
}
|
||||
|
||||
.mt-0 {
|
||||
@@ -26,28 +26,8 @@
|
||||
margin-top: 0.25rem
|
||||
}
|
||||
|
||||
.ml-auto {
|
||||
margin-left: auto
|
||||
}
|
||||
|
||||
.-mb-px {
|
||||
margin-bottom: -1px
|
||||
}
|
||||
|
||||
.mr-1 {
|
||||
margin-right: 0.25rem
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-top: 0.5rem
|
||||
}
|
||||
|
||||
.-mt-2 {
|
||||
margin-top: -0.5rem
|
||||
}
|
||||
|
||||
.-mt-4 {
|
||||
margin-top: -1rem
|
||||
.block {
|
||||
display: block
|
||||
}
|
||||
|
||||
.inline-block {
|
||||
@@ -74,16 +54,12 @@
|
||||
height: 9rem
|
||||
}
|
||||
|
||||
.w-36 {
|
||||
width: 9rem
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.max-w-md {
|
||||
max-width: 28rem
|
||||
.w-36 {
|
||||
width: 9rem
|
||||
}
|
||||
|
||||
.flex-grow {
|
||||
@@ -116,6 +92,10 @@
|
||||
margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)))
|
||||
}
|
||||
|
||||
.rounded-md {
|
||||
border-radius: 0.375rem
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 0.25rem
|
||||
}
|
||||
@@ -128,31 +108,10 @@
|
||||
border-radius: 9999px
|
||||
}
|
||||
|
||||
.rounded-xl {
|
||||
border-radius: 0.75rem
|
||||
}
|
||||
|
||||
.rounded-lg {
|
||||
border-radius: 0.5rem
|
||||
}
|
||||
|
||||
.rounded-md {
|
||||
border-radius: 0.375rem
|
||||
}
|
||||
|
||||
.rounded-t {
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0.25rem
|
||||
}
|
||||
|
||||
.border-2 {
|
||||
border-width: 2px
|
||||
}
|
||||
|
||||
.border {
|
||||
border-width: 1px
|
||||
}
|
||||
|
||||
.border-b-8 {
|
||||
border-bottom-width: 8px
|
||||
}
|
||||
@@ -161,90 +120,21 @@
|
||||
border-bottom-width: 2px
|
||||
}
|
||||
|
||||
.border-b {
|
||||
border-bottom-width: 1px
|
||||
}
|
||||
|
||||
.border-l {
|
||||
border-left-width: 1px
|
||||
}
|
||||
|
||||
.border-t {
|
||||
border-top-width: 1px
|
||||
}
|
||||
|
||||
.border-r {
|
||||
border-right-width: 1px
|
||||
}
|
||||
|
||||
.border-purple-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(168 85 247 / var(--tw-border-opacity))
|
||||
}
|
||||
|
||||
.border-purple-100 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(243 232 255 / var(--tw-border-opacity))
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity))
|
||||
}
|
||||
|
||||
.bg-blue-900\/20 {
|
||||
background-color: rgb(30 58 138 / 0.2)
|
||||
}
|
||||
|
||||
.bg-purple-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(168 85 247 / var(--tw-bg-opacity))
|
||||
}
|
||||
|
||||
.bg-purple-700 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(126 34 206 / var(--tw-bg-opacity))
|
||||
}
|
||||
|
||||
.bg-purple-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(88 28 135 / var(--tw-bg-opacity))
|
||||
}
|
||||
|
||||
.p-4 {
|
||||
padding: 1rem
|
||||
}
|
||||
|
||||
.p-6 {
|
||||
padding: 1.5rem
|
||||
}
|
||||
|
||||
.p-1 {
|
||||
padding: 0.25rem
|
||||
}
|
||||
|
||||
.p-3 {
|
||||
padding: 0.75rem
|
||||
}
|
||||
|
||||
.px-4 {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem
|
||||
}
|
||||
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem
|
||||
}
|
||||
|
||||
.px-2 {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem
|
||||
}
|
||||
|
||||
.py-16 {
|
||||
padding-top: 4rem;
|
||||
padding-bottom: 4rem
|
||||
.p-4 {
|
||||
padding: 1rem
|
||||
}
|
||||
|
||||
.py-2\.5 {
|
||||
@@ -252,24 +142,14 @@
|
||||
padding-bottom: 0.625rem
|
||||
}
|
||||
|
||||
.px-3 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem
|
||||
}
|
||||
|
||||
.py-0 {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px
|
||||
}
|
||||
|
||||
.py-1 {
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem
|
||||
}
|
||||
|
||||
.py-0\.5 {
|
||||
padding-top: 0.125rem;
|
||||
padding-bottom: 0.125rem
|
||||
.px-4 {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem
|
||||
}
|
||||
|
||||
.pb-2 {
|
||||
@@ -280,14 +160,15 @@
|
||||
padding-bottom: 0.25rem
|
||||
}
|
||||
|
||||
.pt-4 {
|
||||
padding-top: 1rem
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.text-sm {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem
|
||||
}
|
||||
|
||||
.text-4xl {
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.5rem
|
||||
@@ -303,11 +184,6 @@
|
||||
line-height: 2rem
|
||||
}
|
||||
|
||||
.text-sm {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem
|
||||
}
|
||||
|
||||
.font-extrabold {
|
||||
font-weight: 800
|
||||
}
|
||||
@@ -316,18 +192,6 @@
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
.font-semibold {
|
||||
font-weight: 600
|
||||
}
|
||||
|
||||
.font-medium {
|
||||
font-weight: 500
|
||||
}
|
||||
|
||||
.leading-5 {
|
||||
line-height: 1.25rem
|
||||
}
|
||||
|
||||
.text-neutral-900 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(23 23 23 / var(--tw-text-opacity))
|
||||
@@ -338,21 +202,6 @@
|
||||
color: rgb(115 115 115 / var(--tw-text-opacity))
|
||||
}
|
||||
|
||||
.text-blue-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(29 78 216 / var(--tw-text-opacity))
|
||||
}
|
||||
|
||||
.text-blue-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(59 130 246 / var(--tw-text-opacity))
|
||||
}
|
||||
|
||||
.text-blue-100 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(219 234 254 / var(--tw-text-opacity))
|
||||
}
|
||||
|
||||
.\!no-underline {
|
||||
-webkit-text-decoration-line: none !important;
|
||||
text-decoration-line: none !important
|
||||
@@ -364,32 +213,10 @@
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)
|
||||
}
|
||||
|
||||
.ring-white {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity))
|
||||
}
|
||||
|
||||
.ring-opacity-60 {
|
||||
--tw-ring-opacity: 0.6
|
||||
}
|
||||
|
||||
.ring-offset-2 {
|
||||
--tw-ring-offset-width: 2px
|
||||
}
|
||||
|
||||
.ring-offset-blue-400 {
|
||||
--tw-ring-offset-color: #60a5fa
|
||||
}
|
||||
|
||||
.hover\:bg-white\/\[0\.12\]:hover {
|
||||
background-color: rgb(255 255 255 / 0.12)
|
||||
}
|
||||
|
||||
.hover\:text-blue-800:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(30 64 175 / var(--tw-text-opacity))
|
||||
}
|
||||
|
||||
.hover\:text-white:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity))
|
||||
@@ -400,18 +227,7 @@
|
||||
outline-offset: 2px
|
||||
}
|
||||
|
||||
.focus\:ring-2:focus {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.dark\:border-purple-900 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(88 28 135 / var(--tw-border-opacity))
|
||||
}
|
||||
|
||||
.dark\:text-neutral-400 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(163 163 163 / var(--tw-text-opacity))
|
||||
@@ -422,11 +238,6 @@
|
||||
.sm\:flex-row {
|
||||
flex-direction: row
|
||||
}
|
||||
|
||||
.sm\:px-0 {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
|
@@ -150,15 +150,20 @@ You have plenty choices here according to your budget !
|
||||
|
||||
Here some of the cheapest VPS options we have :
|
||||
|
||||
* **CPX11 (AMD)** = 2C/2G/40Go = **€4.79**
|
||||
* **CX21 (Intel)** = 3C/4G/80Go = **€5.88**
|
||||
* **CPX21 (AMD)** = 3C/4G/80Go = **€8.28**
|
||||
| Server Type | Spec | Price |
|
||||
| ---------------- | ---------- | --------- |
|
||||
| **CPX11 (AMD)** | 2C/2G/40Go | **€4.79** |
|
||||
| **CX21 (Intel)** | 3C/4G/80Go | **€5.88** |
|
||||
| **CPX21 (AMD)** | 3C/4G/80Go | **€8.28** |
|
||||
|
||||
My personal choice for a good balance between cheap and well-balanced cluster :
|
||||
|
||||
* `manager-01` : **CX21**, I'll privilege RAM
|
||||
* `runner-01` : **CPX11**, 2 powerful core is better for building
|
||||
* `worker-01` and `data-01` : **CX21 VS CPX21** (just a power choice matter)
|
||||
| Server Name | Type | Why |
|
||||
| ------------ | --------------------- | -------------------------------------------- |
|
||||
| `manager-01` | **CX21** | I'll privilege RAM |
|
||||
| `runner-01` | **CPX11** | 2 powerful core is better for building |
|
||||
| `worker-01` | **CX21** or **CPX21** | Just a power choice matter for your app |
|
||||
| `data-01` | **CX21** or **CPX21** | Just a power choice matter for your database |
|
||||
|
||||
We'll take additional volume of **60 Go** for **€2.88**
|
||||
|
||||
@@ -179,23 +184,116 @@ If you intend to have your own self-hosted GitLab for an enterprise grade CI/CD
|
||||
Before continue I presume you have :
|
||||
|
||||
* Hetzner cloud account ready
|
||||
* Configured [hcloud cli](https://github.com/hetznercloud/cli)
|
||||
* Installed [hcloud cli](https://github.com/hetznercloud/cli)
|
||||
* Have a local account SSH key
|
||||
|
||||
Firstly create the new context for your new project :
|
||||
Initiate the project by following this simple steps :
|
||||
|
||||
{{< tabs tabTotal="2" >}}
|
||||
{{< tab tabName="Bash" >}}
|
||||
1. Create the project through the UI (I will use `swarm-rocks` as project's name here)
|
||||
2. Navigate to security > API tokens
|
||||
3. Generate new API key with Read Write permissions and copy the generated token
|
||||
|
||||
Then go to the terminal and prepare the new context
|
||||
|
||||
```sh
|
||||
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1
|
||||
hcloud context create swarm-rocks # set the copied token at prompt
|
||||
hcloud context list # check that your new project is active
|
||||
|
||||
# set your ssh key to the project
|
||||
hcloud ssh-key create --name swarm --public-key-from-file .ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab tabName="Powershell" >}}
|
||||
Now we are ready to set up the above architecture !
|
||||
|
||||
```powershell
|
||||
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 64 | % {[char]$_})
|
||||
### Create the required servers and networks
|
||||
|
||||
```sh
|
||||
# create private network
|
||||
hcloud network create --name network-01 --ip-range 10.0.0.0/16
|
||||
|
||||
# create manager server
|
||||
hcloud server create --name manager-01 --ssh-key swarm --image ubuntu-20.04 --type cx21 --location nbg1 --network network-01
|
||||
|
||||
# create worker server
|
||||
hcloud server create --name worker-01 --ssh-key swarm --image ubuntu-20.04 --type cx21 --location nbg1 --network network-01
|
||||
|
||||
# create runner server
|
||||
hcloud server create --name runner-01 --ssh-key swarm --image ubuntu-20.04 --type cpx11 --location nbg1 --network network-01
|
||||
|
||||
# create data server
|
||||
hcloud server create --name data-01 --ssh-key swarm --image ubuntu-20.04 --type cx21 --location nbg1 --network network-01
|
||||
|
||||
# create the volume that will be used by gluster
|
||||
hcloud volume create --name volume-01 --size 60 --location nbg1 --automount --server data-01
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
### Prepare the servers
|
||||
|
||||
```sh
|
||||
# ssh to your server
|
||||
hcloud server ssh manager-01
|
||||
```
|
||||
|
||||
```sh
|
||||
# ssh to your server
|
||||
hcloud server ssh worker-01
|
||||
```
|
||||
|
||||
### The firewall
|
||||
|
||||
You should never let any cluster without properly configured firewall. It's generally preferable to use the cloud provider firewall instead of standard `ufw` because more easy to manage, no risk of being stupidly blocked, and settled once and for all.
|
||||
|
||||
You need at least 2 firewalls :
|
||||
|
||||
1. One for external incoming for SSH and Traefik, you'll need a full set of rules, only enabled for `manager-01`
|
||||
2. The second for block all any incoming requests applied to any servers different from the manager
|
||||
|
||||
{{< alert >}}
|
||||
You wonder how we can access to this servers then, at least for ssh.
|
||||
{{< /alert >}}
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"direction": "in",
|
||||
"port": "22",
|
||||
"protocol": "tcp",
|
||||
"source_ips": [
|
||||
"0.0.0.0/0",
|
||||
"::/0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"direction": "in",
|
||||
"port": "80",
|
||||
"protocol": "tcp",
|
||||
"source_ips": [
|
||||
"0.0.0.0/0",
|
||||
"::/0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"direction": "in",
|
||||
"port": "443",
|
||||
"protocol": "tcp",
|
||||
"source_ips": [
|
||||
"0.0.0.0/0",
|
||||
"::/0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"direction": "in",
|
||||
"port": "2222",
|
||||
"protocol": "tcp",
|
||||
"source_ips": [
|
||||
"123.123.123.123/32"
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```sh
|
||||
# prepare firewall
|
||||
hcloud firewall create --name firewall-internal
|
||||
hcloud firewall create --name firewall-external --rules-file firewall-rules.json
|
||||
```
|
||||
|
Reference in New Issue
Block a user