Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# Contributing to LIDSOL Infrastructure

Thank you for your interest in contributing to the LIDSOL infrastructure repository! This document explains how to get started, what kinds of contributions are welcome, and how the review process works.

## Table of Contents

- [Code of Conduct](#code-of-conduct)
- [Ways to Contribute](#ways-to-contribute)
- [Getting Started](#getting-started)
- [Development Workflow](#development-workflow)
- [Making Changes](#making-changes)
- [Ansible Playbooks and Roles](#ansible-playbooks-and-roles)
- [Kubernetes Manifests (GitOps)](#kubernetes-manifests-gitops)
- [Documentation](#documentation)
- [Commit Messages](#commit-messages)
- [Pull Request Process](#pull-request-process)
- [Reporting Issues](#reporting-issues)
- [Contact](#contact)

## Code of Conduct

This project follows UNAM's community standards. We expect all contributors to be respectful, constructive, and collaborative. Harassment or discrimination of any kind will not be tolerated.

## Ways to Contribute

- **Bug reports**: Open an issue describing a misconfiguration, broken deployment, or unexpected behavior.
- **Feature requests**: Suggest new services, roles, or infrastructure improvements.
- **Documentation**: Improve or translate any documentation file.
- **Ansible roles**: Add new roles or improve existing ones (security, mirrors, network, etc.).
- **Kubernetes manifests**: Add new application deployments to `gitops/` or tune existing ones.
- **Security improvements**: Harden configurations, reduce attack surfaces, or update vulnerable components.

## Getting Started

### 1. Fork and clone

```bash
# Fork the repo on GitHub, then:
git clone --recurse-submodules https://github.com/<your-username>/infra.git
cd infra
```

### 2. Install prerequisites

| Tool | Minimum Version |
|------|----------------|
| [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/) | 2.14 |
| [kubectl](https://kubernetes.io/docs/tasks/tools/) | 1.28 |
| [Git](https://git-scm.com/) | 2.40 |
| Python | 3.10 |

Install Ansible collections used in this repo:

```bash
ansible-galaxy collection install community.general
```

### 3. Set up a test environment

> **Important**: Never test changes directly against production nodes without first verifying them in a safe environment. Use local VMs (e.g., with Vagrant or Multipass) or dedicated test machines.

```bash
# Example: spin up test VMs with multipass
multipass launch --name test-node --cpus 2 --memory 2G
```

## Development Workflow

```
fork → clone → branch → change → test → commit → push → pull request
```

1. Create a branch from `main`:
```bash
git checkout -b feat/my-feature
```
2. Make your changes (see [Making Changes](#making-changes) below).
3. Test your changes in a non-production environment.
4. Commit your changes following the [commit message guidelines](#commit-messages).
5. Push and open a pull request against `main`.

## Making Changes

### Ansible Playbooks and Roles

- Follow the standard [Ansible best practices](https://docs.ansible.com/ansible/latest/tips_tricks/ansible_tips_tricks.html).
- Keep tasks idempotent: running a playbook multiple times must always produce the same result.
- Use **roles** for logically grouped tasks (e.g., `security`, `nginx`, `mirrors`).
- Store sensitive values (passwords, tokens, keys) in **Ansible Vault** — never commit them in plain text.
- Use descriptive `name:` fields on every task.
- Prefer YAML block scalars over long single-line strings.
- Add or update the relevant `docs/` file when introducing a new role or changing an existing one significantly.

**Running a playbook in check mode** (dry run, no changes applied):

```bash
ansible-playbook -i public-server/inventory.yml public-server/main.yaml --check
```

**Limiting execution to a single host or role**:

```bash
# Single host
ansible-playbook -i public-server/inventory.yml public-server/main.yaml --limit mirrors

# Single tag
ansible-playbook -i public-server/inventory.yml public-server/main.yaml --tags nginx
```

**Linting Ansible files**:

```bash
pip install ansible-lint
ansible-lint public-server/main.yaml
```

### Kubernetes Manifests (GitOps)

All Kubernetes manifests live in `gitops/`. ArgoCD watches this directory and automatically applies changes when they are merged to `main`.

- One manifest file per application (e.g., `gitops/myapp-deployment.yaml`).
- Always specify resource `requests` and `limits` for CPU and memory.
- Use `Namespace` resources within the manifest when a dedicated namespace is needed.
- Prefer `ClusterIssuer` and `Certificate` resources from cert-manager for TLS — do not store TLS secrets in the repository.
- For `LoadBalancer` services that require a static IP from MetalLB, annotate the service with the desired IP:
```yaml
metadata:
annotations:
metallb.universe.tf/loadBalancerIPs: "10.8.24.1XX"
```

**Validate manifests before committing**:

```bash
kubectl apply --dry-run=client -f gitops/myapp-deployment.yaml
```

### Documentation

- Documentation lives in `docs/` (detailed per-component guides) and in the root `README.md` and `CONTRIBUTING.md`.
- Write in English; Spanish is also acceptable for documents that are primarily read by the local team.
- Use [Markdown](https://www.markdownlang.org/). Keep lines under 120 characters.
- Update the table of contents in any file you modify if it has one.
- Reference related files with relative links (e.g., `[cluster.md](docs/cluster.md)`).

## Commit Messages

Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:

```
<type>(<scope>): <short summary>

[optional body]

[optional footer]
```

**Types**:

| Type | When to use |
|------|------------|
| `feat` | New feature or new Ansible role |
| `fix` | Bug fix or misconfiguration correction |
| `docs` | Documentation-only changes |
| `refactor` | Code restructuring without behavior change |
| `chore` | Dependency updates, minor maintenance |
| `security` | Security-related hardening or patch |

**Examples**:

```
feat(mirrors): add Fedora mirror sync role

fix(router): correct nftables masquerade rule for WAN interface

docs(cluster): document MetalLB IP range configuration

security(ssh): disable root login in sshd hardening task
```

## Pull Request Process

1. Ensure your branch is up to date with `main`:
```bash
git fetch origin
git rebase origin/main
```
2. Open a pull request against `main` on GitHub.
3. Fill in the pull request template:
- Describe **what** changed and **why**.
- List any manual steps required (e.g., rotating a secret, running a migration).
- Reference related issues with `Closes #<issue-number>`.
4. At least **one maintainer review** is required before merging.
5. All checks (if any CI workflows are configured) must pass.
6. The PR author is responsible for resolving review comments.
7. Squash or rebase commits before merging if the history is noisy.

> **Production changes**: Any change that will affect production infrastructure (playbooks, K8s manifests) must be tested in a staging or dev environment first and documented in the PR description.

## Reporting Issues

Use the [GitHub Issues](https://github.com/LIDSOL/infra/issues) tracker to report bugs or request features.

When reporting a bug, please include:

- A clear title and description of the problem.
- Steps to reproduce (which playbook/command was run, against which host).
- Expected behavior vs. actual behavior.
- Relevant log output or error messages.
- Environment details (OS, Ansible version, Kubernetes version if applicable).

## Contact

- **Email**: lidsol-info@proton.me
- **GitHub**: [@LIDSOL](https://github.com/LIDSOL)
- **Website**: [lidsol.unam.mx](https://lidsol.unam.mx)
176 changes: 176 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# LIDSOL Infrastructure

[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)

Infrastructure-as-code repository for [LIDSOL](https://lidsol.unam.mx) (Laboratorio de Investigación y Desarrollo de Software Libre) at UNAM. This repository manages the full stack: a production Kubernetes cluster, public-facing services, Linux distribution mirrors, and the underlying network.

## Table of Contents

- [Architecture Overview](#architecture-overview)
- [Repository Structure](#repository-structure)
- [Prerequisites](#prerequisites)
- [Quick Start](#quick-start)
- [Components](#components)
- [Contributing](#contributing)
- [License](#license)

## Architecture Overview

```
Internet
┌─────────────────────────────────────────────────────────────────────┐
│ Router / Gateway (Armbian) │
│ WAN: 132.248.59.72/24 ──► LAN: 10.8.24.0/24 │
│ nftables firewall, DNSmasq, WireGuard VPN │
└──────────────────────────────┬──────────────────────────────────────┘
│ LAN
┌──────────────────┼──────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ hp-alpha │ │ hp-beta │ │ gamma │
│K3s master│ │K3s agent │ │K3s agent │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└──────────────────┼──────────────────┘
┌──────────▼──────────┐
│ Kubernetes (K3s) │
│ API: 10.8.24.101 │
│ MetalLB: .102-.120 │
│ │
│ ArgoCD (GitOps) │
│ Cert-Manager │
│ Ingress-Nginx │
│ Longhorn (storage) │
│ LIDSOL Website │
│ Nextcloud │
│ DrawDB │
│ Speedtest Tracker │
└─────────────────────┘

Public Server (lidsol.fi-b.unam.mx)
Nginx + Let's Encrypt
Linux Mirrors: AlmaLinux, ArchLinux, Debian, Fedora, Linux Mint
```

## Repository Structure

```
infra/
├── README.md # This file
├── CONTRIBUTING.md # How to contribute
├── LICENSE # Apache 2.0 License
├── docs/ # Detailed documentation
│ ├── cluster.md # K3s cluster setup and management
│ ├── gitops.md # GitOps / ArgoCD deployments
│ ├── public-server.md # Public server (mirrors, router, security)
│ └── mirrors.md # Linux distribution mirrors
├── cluster/ # Kubernetes cluster provisioning
│ ├── argo-config/ # ArgoCD application manifests
│ ├── config/ # Ansible inventory and variables
│ ├── k3s-ansible/ # Git submodule: k3s-ansible
│ ├── node.yml # Ansible playbook: node preparation
│ └── argocd.yml # Ansible playbook: ArgoCD + Longhorn install
├── gitops/ # Kubernetes manifests (managed by ArgoCD)
│ ├── certmanager-deployment.yaml
│ ├── ingress-deployment.yaml
│ ├── longhorn-ui-deployment.yaml
│ ├── nextcloud-deployment.yaml
│ ├── website-deployment.yaml
│ ├── https-issuer-deployment.yaml
│ ├── drawdb-deployment.yaml
│ ├── speedtest-tracker-deployment.yaml
│ └── ExplicacionIngress.md # Ingress controller documentation (Spanish)
└── public-server/ # Public server configuration
├── main.yaml # Main Ansible playbook
├── inventory.yml # Ansible inventory
├── security/ # Role: SSH hardening + automatic updates
├── network/ # Role: IRQ balancing + sysctl tuning
├── nginx/ # Role: Nginx + Let's Encrypt
├── router/ # Role: routing, firewall, VPN, DNS
└── mirrors/ # Role: Linux distribution mirrors
```

## Prerequisites

The following tools must be installed on your workstation before working with this repository.

| Tool | Minimum Version | Purpose |
|------|----------------|---------|
| [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/) | 2.14 | Configuration management and playbook execution |
| [kubectl](https://kubernetes.io/docs/tasks/tools/) | 1.28 | Kubernetes cluster management |
| [Git](https://git-scm.com/) | 2.40 | Version control and submodule support |
| Python | 3.10 | Required by Ansible |

> **Note**: Access to the cluster nodes via SSH (with your key in `cluster/config/authorized_keys`) is required for cluster operations.

## Quick Start

### 1. Clone the repository

```bash
git clone --recurse-submodules https://github.com/LIDSOL/infra.git
cd infra
```

If you already cloned without `--recurse-submodules`:

```bash
git submodule update --init --recursive
```

### 2. Set up the Kubernetes cluster

See [docs/cluster.md](docs/cluster.md) for full details.

```bash
# 1. Configure node variables
cp cluster/config/host_vars/hp-alpha.yml cluster/config/host_vars/<your-node>.yml
# Edit the file with your node's IP and network settings

# 2. Prepare the nodes
ansible-playbook -i cluster/config/hosts.ini cluster/node.yml

# 3. Deploy K3s
ansible-playbook -i cluster/config/hosts.ini cluster/k3s-ansible/site.yml

# 4. Install ArgoCD and Longhorn
ansible-playbook -i cluster/config/hosts.ini cluster/argocd.yml
```

### 3. Configure the public server

See [docs/public-server.md](docs/public-server.md) for full details.

```bash
# Review and update the inventory
vim public-server/inventory.yml

# Run the main playbook
ansible-playbook -i public-server/inventory.yml public-server/main.yaml
```

### 4. Deploy applications via GitOps

Once ArgoCD is running, it automatically syncs manifests from the `gitops/` directory. See [docs/gitops.md](docs/gitops.md) for details.

## Components

| Component | Documentation | Description |
|-----------|--------------|-------------|
| K3s Cluster | [docs/cluster.md](docs/cluster.md) | Lightweight Kubernetes cluster on bare metal |
| GitOps | [docs/gitops.md](docs/gitops.md) | ArgoCD-managed application deployments |
| Public Server | [docs/public-server.md](docs/public-server.md) | Nginx, routing, security, and mirrors |
| Mirrors | [docs/mirrors.md](docs/mirrors.md) | Linux distribution mirror setup and sync |

## Contributing

We welcome contributions of all kinds — bug fixes, documentation improvements, new features, and feedback.

Please read [CONTRIBUTING.md](CONTRIBUTING.md) before submitting a pull request.

## License

This project is licensed under the [Apache License 2.0](LICENSE).
Loading