1.0.0 Release IaaS
This commit is contained in:
146
docs/services/infra/ca.md
Normal file
146
docs/services/infra/ca.md
Normal file
@@ -0,0 +1,146 @@
|
||||
## Operation
|
||||
Refer to Ansible playbook
|
||||
|
||||
## Configuration files
|
||||
|
||||
- ca.json
|
||||
- defaults.json
|
||||
|
||||
### Provisioner
|
||||
|
||||
Provisioner is basically the object of issuing certificates as a RA. They verify CSR from client and when it is valid with its policy they will sign the certificates with CA's private key. Step-CA supports various type of provisioner. In this homelab, only ACME will be used. Because infrastructure's certificates is issued manually. Step-CA supports one root CA and one intermediate CA in one container, only one intermediate CA will be operated in this project.
|
||||
|
||||
#### jwk-ca@ilnmors.internal
|
||||
|
||||
This provisioner is to issue intermediate CA. It wouldn't be used in this project. The option for CA in X.509 format is optional and defined in as extension option. To define these option in step-ca, the template file is needed.
|
||||
|
||||
- file: ~/data/containers/step-ca/templates/ca.tpl
|
||||
|
||||
```json
|
||||
{
|
||||
"subject": {{ toJson .Subject }},
|
||||
"keyUsage": ["certSign", "crlSign"],
|
||||
"basicConstraints": {
|
||||
"isCA": true,
|
||||
"maxPathLen": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> keyUsage: Designate to manage certificates and CRL
|
||||
> isCA: Designate the certificate to use CA
|
||||
> maxPathLen: Designate allowed below CA's number
|
||||
|
||||
|
||||
- Define provisioner
|
||||
|
||||
```bash
|
||||
podman exec -it step-ca \
|
||||
step ca provisioner add jwk-ca@ilnmors.internal \
|
||||
--create \ # Generate key pair automatically
|
||||
--type JWK \
|
||||
--ca-config /home/step/config/ca.json \ # Sign on certificate with root CA's private key
|
||||
--x509-template /home/step/template/ca.tpl \ # Use x509 template
|
||||
--x509-max-dur 87600h \ #
|
||||
--x509-default-dur 87600h
|
||||
```
|
||||
|
||||
#### jwk@ilnmors.internal
|
||||
|
||||
This provisioner is to issue the certificates like DB communication based on its identity (Using JWK and JWT pre-shared). The certificate is issued based on enrolled key in provisioner. However, in this project all crt will be used central ACME client `Caddy`.
|
||||
|
||||
- Define provisioner
|
||||
|
||||
```bash
|
||||
podman exec -it step-ca \
|
||||
step ca provisioner add jwk@ilnmors.internal \
|
||||
--create \ # Generate key pair automatically
|
||||
--type JWK \
|
||||
--x509-default-dur 2160h # To set default expire date as 90 days.
|
||||
```
|
||||
|
||||
#### acme@ilnmors.internal
|
||||
|
||||
This provisioner is to issue the certificates for https communication. The certificate is issued based on challenge; the ownership of domain.
|
||||
|
||||
- Define provisioner
|
||||
```bash
|
||||
podman exec -it step-ca \
|
||||
step ca provisioner add acme@ilnmors.internal \
|
||||
--type ACME \
|
||||
--x509-default-dur 2160h # To set default expire date as 90 days.
|
||||
```
|
||||
|
||||
### Subject
|
||||
|
||||
Step-CA uses subject as a account. It is used to manage Step-CA remotely. To use this, it is necessary to use `--remote-management` option when the step-CA is initially set or fix `ca.json` authority.enableAdmin:true. When subject is enabled, provisioners aren't defined in ca.json but its own DB.
|
||||
|
||||
### Policy
|
||||
|
||||
Self-hosted Step-CA server doesn't support to give x509 policy for each provisioner. It only allows public policy. Only `ilnmors.internal` and `*.ilnmors.internal` certificates are required, so designate the policy in `ca.json`
|
||||
|
||||
> Policies can be administered using the step CLI application. The commands are part of the step ca policy namespace. In a self-hosted step-ca, policies can be configured on the authority level. Source: [here](https://smallstep.com/docs/step-ca/policies/)
|
||||
|
||||
- file: ~/data/containers/step-ca/config/ca.json
|
||||
|
||||
```json
|
||||
...
|
||||
"authority": {
|
||||
"policy": {
|
||||
"x509": {
|
||||
"allow": {
|
||||
"dns": [
|
||||
"ilnmors.internal",
|
||||
"*.ilnmors.internal"
|
||||
]
|
||||
},
|
||||
"allowWildcardNames": true
|
||||
}
|
||||
},
|
||||
"provisioners": [ ... ]
|
||||
....
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
## Verify server
|
||||
|
||||
### Server health check
|
||||
|
||||
```bash
|
||||
curl -k https://ca.ilnmors.internal:9000/health
|
||||
> {"status":"ok"}
|
||||
```
|
||||
|
||||
### Server policy check
|
||||
|
||||
```bash
|
||||
podman exec -it ca step ca certificate test.com test.crt test_key --provisioner acme@ilnmors.internal
|
||||
> error creating new ACME order: The server will not issue certificates for the identifier
|
||||
```
|
||||
|
||||
---
|
||||
## Set trust Root CRT
|
||||
|
||||
### Linux
|
||||
|
||||
#### Debian/ubuntu
|
||||
|
||||
- File: /usr/local/share/ca-certificates/{ca.crt, ca.pem}
|
||||
- `update-ca-certificates`
|
||||
|
||||
#### Cent/RHEL/Fedora
|
||||
|
||||
- File: /etc/pki/ca-trust/source/anchors/{ca.crt, ca.pem}
|
||||
- `update-ca-trust`
|
||||
|
||||
### Windows
|
||||
|
||||
- `Windows + R` + `certlm.msc`
|
||||
- `All Task` - `Import`
|
||||
|
||||
### Firefox
|
||||
|
||||
- Setting - Security - view certificates - Authority - add
|
||||
- \[x\] trust this ca to identify website
|
||||
- \[x\] trust this ca to identify email users
|
||||
20
docs/services/infra/grafana.md
Normal file
20
docs/services/infra/grafana.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Grafana
|
||||
|
||||
## Operation
|
||||
Refer to Ansible playbook
|
||||
\(Postgresql user and DB is needed\)
|
||||
\(LDAP strict readonly account is needed\)
|
||||
|
||||
## Verification
|
||||
- Check Caddyfile \(without caddy, use 3000 ports\)
|
||||
- https://grafana.ilnmors.internal
|
||||
- login with LDAP user
|
||||
- connection:data sources: \[prometheus|loki\]: provisioned
|
||||
- https://prometheus.ilnmors.internal:9090
|
||||
- https://loki.ilnmors.internal:3100
|
||||
|
||||
- check drill down:metrics
|
||||
|
||||
## Dashboard
|
||||
|
||||
- Dashboard isn't saved on local directory. They are saved on DB \(Postgresql\).
|
||||
154
docs/services/infra/ldap.md
Normal file
154
docs/services/infra/ldap.md
Normal file
@@ -0,0 +1,154 @@
|
||||
## Operation
|
||||
Refer to Ansible playbook
|
||||
\(Postgresql user and DB is needed\)
|
||||
|
||||
Integrate configuration with various app: https://github.com/lldap/lldap/blob/main/example_configs
|
||||
|
||||
## Configuration
|
||||
### DB URL
|
||||
|
||||
Jinja2 `urlencode` module doesn't replace `/` as `%2F`. replace('/', '%2F') is necessary.
|
||||
ex\) {{ var | urlencode | replace('/', '%2F') }}
|
||||
|
||||
### Reset administrator password
|
||||
|
||||
```bash
|
||||
# infra
|
||||
sudo nano $LDAP_PATH/data/lldap_config.toml
|
||||
# Add below on file
|
||||
ldap_user_pass = "REPLACE_WITH_PASSWORD"
|
||||
force_ldap_user_pass_reset = true
|
||||
# Restart lldap
|
||||
systemctl --user restart ldap.service
|
||||
# Delete added lines from lldap_config.toml
|
||||
# ldap_user_pass = "REPLACE_WITH_PASSWORD"
|
||||
# *YOU MUST DELETE PASSWORD PART*
|
||||
# force_ldap_user_pass_reset = true
|
||||
```
|
||||
|
||||
### Access web UI and Login
|
||||
|
||||
- URL: http://ldap.ilnmors.internal:17170 \(This is temporary access way before Caddy, which is reverse proxy, is set)
|
||||
- ID: admin
|
||||
- PW: $LLDAP_LDAP_USER_PASSWORD
|
||||
|
||||
### Create the groups
|
||||
|
||||
- Groups - \[\+\] Create a group
|
||||
- Group: admins
|
||||
- Group: users
|
||||
|
||||
It is necessary to manage ACL via authelia based on groups.
|
||||
|
||||
### Create the authelia user for OCID \(OP\)
|
||||
|
||||
- Users: \[\+\] Create a user
|
||||
- Username (cn; uid): authelia
|
||||
- Display name: Authelia
|
||||
- First Name: Authelia
|
||||
- Last Name (sn): Service
|
||||
- Email (mail): authelia@ilnmors.internal
|
||||
- Password: "$(openssl rand -base64 32)"
|
||||
- Groups:lldap_strict_readonly: \[Add to group\]
|
||||
- This group allow search authority.
|
||||
- Users: \[\+\] Create a user
|
||||
- Username (cn; uid): grafana
|
||||
- Display name: Grafana
|
||||
- First Name: Grafana
|
||||
- Last Name (sn): Service
|
||||
- Email (mail): grafana@ilnmors.internal
|
||||
- Password: "$(openssl rand -base64 32)"
|
||||
- Groups:lldap_strict_readonly: \[Add to group\]
|
||||
- This group allow search authority.
|
||||
> Save the password in .secret.yaml
|
||||
|
||||
### Create the normal users
|
||||
|
||||
- Users: \[\+\] Create a user
|
||||
- Username (cn; uid): il
|
||||
- First Name: Il
|
||||
- Last Name (sn): Lee
|
||||
- Email (mail): il@ilnmors.internal
|
||||
- Password: "$PASSWORD"
|
||||
- Groups:lldap_admin&admins&users: \[Add to group\]
|
||||
- Users: \[\+\] Create a user
|
||||
- Username (cn; uid): user
|
||||
- First Name: John
|
||||
- Last Name (sn): Doe
|
||||
- Email (mail): john_doe@ilnmors.internal
|
||||
- Password: "$PASSWORD"
|
||||
- Groups:(admins|users): \[Add to group\]
|
||||
|
||||
> Custom schema in `User schema`, `Group schema` doesn't need to be added. This is for advanced function to add additional value such as `identity number` or `phone number`. Hardcoded schema, which means basic schema the lldap provides is enough to use Authelia.
|
||||
|
||||
> After all these steps, now you can integrate the Authelia for SSO.
|
||||
|
||||
## Usage of LDAP
|
||||
|
||||
### Service Bind
|
||||
|
||||
LDAP call `login` as Bind. When the authelia Bind to the LDAP server, it can get the authority to search in `lldap_strict_readonly` group.
|
||||
|
||||
### Search
|
||||
|
||||
authelia account has the authority to search, it can search to send the query.
|
||||
|
||||
#### Flow of search
|
||||
|
||||
- Client (authelia) sends the query
|
||||
- `uid=user in dc=ilnmors,dc=internal`
|
||||
- LDAP server searches the DN of entry
|
||||
- `uid=user,ou=people,dc=ilnmors,dc=internal`
|
||||
- LDAP sends the DN to Client (authelia)
|
||||
|
||||
## Authelia's work flow
|
||||
|
||||
### First login
|
||||
|
||||
#### User login query
|
||||
|
||||
User try to login on login page of Authelia.
|
||||
|
||||
- id: user
|
||||
- password: 1234
|
||||
|
||||
#### Service Bind (Bind and search)
|
||||
|
||||
authelia binds to LLDAP server based on the information in configuration.yml.
|
||||
|
||||
- dn: authelia
|
||||
- password: authelia's password
|
||||
|
||||
#### Search
|
||||
|
||||
authelia sends the query to LLDAP after bind.
|
||||
- `uid=user in dc=ilnmors,dc=internal`
|
||||
|
||||
#### Request
|
||||
|
||||
LLDAP server searches the entry and send the DN information query to authelia.
|
||||
|
||||
- `uid=user,ou=people,dc=ilnmors,dc=internal`
|
||||
|
||||
### Verify the user login (Second login)
|
||||
|
||||
#### User Bind (Bind only)
|
||||
|
||||
authelia tries to bind LLDAP server based on the information that user input.
|
||||
|
||||
- dn: requested uid
|
||||
- password: 1234
|
||||
|
||||
#### Verification from LLDAP
|
||||
|
||||
LLDAP verify the password from authelia with its hash value saved in LLDAP's database.
|
||||
|
||||
#### Request
|
||||
|
||||
LLDAP server sends the result as `Success` or `Fail`.
|
||||
|
||||
> Search authority is basic authority of user who binds to LDAP server. It is just the way to check success or fail bind is the charge of Authelia.
|
||||
|
||||
## verify
|
||||
|
||||
- openssl s_client -connect ldap.ilnmors.internal:636 -tls1_3
|
||||
12
docs/services/infra/loki.md
Normal file
12
docs/services/infra/loki.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# loki
|
||||
|
||||
## Operation
|
||||
Refer to Ansible playbook
|
||||
## Verification
|
||||
- fw@fw:/var/lib/bind$ curl -k https://loki.ilnmors.internal:3100/ready \(Node which is in NET_SERVER except infra itself\)
|
||||
- ready
|
||||
- fw@fw:/var/lib/bind$ curl -k https://loki.ilnmors.internal:3100/metrics
|
||||
- metrics lists
|
||||
- fw@fw:/var/lib/bind$ curl -k https://loki.ilnmors.internal:3100/loki/api/v1/labels
|
||||
- no org id
|
||||
- JSON format labels when alloy is set
|
||||
64
docs/services/infra/postgresql.md
Normal file
64
docs/services/infra/postgresql.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Postgresql
|
||||
|
||||
## Operation
|
||||
Refer to Ansible playbook
|
||||
|
||||
## File management
|
||||
```bash
|
||||
# console
|
||||
## cluster
|
||||
scp infra@infra:$POSTGRESQL_BACKUP_PATH/pg_cluster.sql $HOMELAB_PATH/data/backups/infra/postgresql/pg_cluster.sql
|
||||
## data
|
||||
scp infra@infra:$POSTGRESQL_BACKUP_PATH/pg_backup.sql $HOMELAB_PATH/data/backups/infra/postgresql/pg_backup.sql
|
||||
|
||||
## The data is managed by kopia.
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
# ... Start postgresql service
|
||||
|
||||
# Create user and database
|
||||
podman exec -it -u postgres postgresql "psql -U postgres"
|
||||
> CREATE USER service WITH PASSWORD 'abc';
|
||||
> CREATE DATABASE service_db;
|
||||
> ALTER DATABASE service_db OWNER TO service;
|
||||
> \du
|
||||
> \l
|
||||
> \q
|
||||
|
||||
# Reset database
|
||||
> SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'service_db'; # connection reset
|
||||
> DROP DATABASE service_db;
|
||||
> CREATE DATABASE service_db;
|
||||
> ALTER DATABASE service_db OWNER TO service;
|
||||
> \du
|
||||
> \l
|
||||
> \q
|
||||
|
||||
# Restor database (manually)
|
||||
podman exec -u postgres postgresql "psql -U postgres -f $POSTGRESQL_BACKUP_PATH_IN_CONTAINER/script.sql"
|
||||
|
||||
# Backup service executes
|
||||
systemctl --user start postgresql-cluster-backup.service
|
||||
|
||||
# Stop and remove all data
|
||||
systemctl --stop postgresql
|
||||
sudo find "/home/infra/data/containers/postgresql/data" -mindepth 1 -delete
|
||||
|
||||
# Restore database
|
||||
# Just locate sql files on data_path, and use playbooks
|
||||
|
||||
# Check restoring
|
||||
podman exec -it -u postgres postgresql psql -U postgres
|
||||
> \du
|
||||
> \l
|
||||
|
||||
# Check extension
|
||||
postgres=# SHOW shared_preload_libraries;
|
||||
shared_preload_libraries
|
||||
--------------------------
|
||||
vchord.so
|
||||
(1 row)
|
||||
```
|
||||
12
docs/services/infra/prometheus.md
Normal file
12
docs/services/infra/prometheus.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Prometheus
|
||||
|
||||
## Operation
|
||||
Refer to Ansible playbook
|
||||
## Verification
|
||||
- Check Caddyfile \(without caddy, use 9090 ports\)
|
||||
- https://prometheus.ilnmors.internal
|
||||
- Status:Target Health
|
||||
- Check `Endpoint localhost:9090 ` with green circle
|
||||
- Status:command-line flag
|
||||
- Check `--web.enable-remote-write-receiver: true`
|
||||
|
||||
Reference in New Issue
Block a user