Este repositorio aprovisiona una estación de trabajo Pop!_OS o Ubuntu con una estrategia en dos capas:
- Ansible gestiona la capa base del sistema operativo: repositorios APT, paquetes del sistema, Docker, Flatpak guiado por facts, integración con el gestor de archivos y bootstrap de Nix.
- Nix con Home Manager gestiona el entorno de usuario de forma reproducible: Zsh, utilidades de desarrollo y variables de entorno declarativas.
- El DevContainer permite validar, lintar y evolucionar la configuración sin contaminar el host.
dotfiles/
├── .devcontainer/
│ ├── devcontainer.json
│ └── Dockerfile
├── .ansible-lint
├── ansible.cfg
├── ansible/
│ ├── group_vars/
│ │ └── all/
│ │ └── main.yml
│ ├── inventories/
│ │ └── local/
│ │ └── hosts.yml
│ ├── local.yml
│ └── roles/
│ ├── common/
│ ├── system/
│ ├── apt_repositories/
│ ├── desktop_apps/
│ ├── virt_manager/
│ ├── flatpak/
│ ├── docker/
│ ├── file_manager/
│ └── nix/
├── nix/
│ ├── home.nix
│ └── flake.nix
├── bootstrap.sh
└── README.md
- En el host Pop!_OS o Ubuntu real, ejecuta
./bootstrap.sh. - El script instala
git,curlyansiblesolo si faltan, clona el repositorio en~/my-workstationdesdehttps://github.com/techlogycs/my-workstation.gitpor defecto si hace falta y lanza el playbook local. - El playbook configura APT y, según los flags de
ansible/group_vars/all/main.yml, instala VS Code, Brave, Docker, virt-manager con libvirt, RustDesk nativo, Flatpak en Ubuntu y Pop!_OS, integración con el gestor de archivos y Nix. - Finalmente, Ansible construye y activa Home Manager desde el flake fijado en
nix/.
El playbook usa roles pequeños y etiquetados para que puedas ejecutar solo una parte del aprovisionamiento:
common: validación del host y facts compartidos.system: paquetes base, herramientas de escritorio y shell por defecto.apt_repositories: repositorios y llaves APT de proveedores.desktop_apps: instalación de VS Code, Brave y RustDesk nativo.virt_manager: stack de virtualización local con libvirt y virt-manager.flatpak: Flathub y aplicaciones Flatpak por distro.docker: configuración dedaemon.jsony servicio.file_manager: integración “Open in Code”.nix: instalación de Nix y activación de Home Manager.apt-clean: elimina definiciones legacy de repositorios APT gestionados por el repo, purga paquetes huérfanos y limpia la caché local de APT.nix-clean: limpieza de generaciones antiguas del perfil gestionado de Nix/Home Manager y garbage collection del store.nix-migrate-single-user: desinstala una instalación multiusuario existente de Nix y reprovisiona Nix en modosingle-user.
Ejemplos:
ansible-playbook ansible/local.yml --tags docker
ansible-playbook ansible/local.yml --tags virt-manager
ansible-playbook ansible/local.yml --tags nix,file-manager
ansible-playbook ansible/apt-clean.yml
ansible-playbook ansible/nix-clean.yml
ansible-playbook ansible/nix-migrate-single-user.yml
make install-feature features=thunderbird
make apt-clean
make nix-clean
make nix-migrate-single-user
./bootstrap.sh --only-feature thunderbird
./bootstrap.sh --tags systemEl contenedor existe únicamente para desarrollo y validación de la configuración. Incluye:
ansible-lintyyamllintpara Ansible/YAML.nix,home-manager,statixynixpkgs-fmtpara evaluar, lintar y formatear la configuración Nix.- Extensiones de VS Code orientadas a Ansible, Nix y TOML.
La imagen del DevContainer instala directamente ansible-core, ansible-lint, yamllint y Nix. Después, postCreateCommand solo añade home-manager, statix y nixpkgs-fmt al perfil del usuario y ejecuta nix flake check --impure sobre nix/.
Si ya tenías el DevContainer creado antes de estos cambios, reconstruye el contenedor para que las herramientas nuevas queden disponibles en PATH.
Dentro del DevContainer o en una máquina con las dependencias instaladas:
make lint
make format
ansible-playbook --syntax-check ansible/local.yml
ansible-lint ansible
yamllint .
DOTFILES_USER="$USER" DOTFILES_HOME="$HOME" NIX_SYSTEM="$(nix eval --impure --raw --expr builtins.currentSystem)" nix --extra-experimental-features "nix-command flakes" flake check --impure ./nixEl Makefile expone también objetivos separados:
make lint-ansiblemake lint-nixmake format-ansiblemake format-nixmake install-feature features=thunderbirdmake apt-cleanmake nix-migrate-single-usermake nix-clean
Los componentes opcionales están controlados desde ansible/group_vars/all/main.yml:
- Todos los
feature_flags.*aceptanenabled,disabledoauto. Los booleanos antiguos siguen funcionando porque se normalizan internamente a esos modos. feature_flags.vscode,feature_flags.brave,feature_flags.docker,feature_flags.nixyfeature_flags.git_credential_oauthusanenabledpor defecto. Hoy en díaautose resuelve igual queenabledpara esos componentes, porque no hay una detección de alternativa equivalente.- Si detecta
docker-desktop, el playbook falla de forma explícita antes de instalar Docker Engine. Para reemplazarlo, debes aprobarlo condocker_desktop_cleanup_approved: true; ese flujo elimina el paquetedocker-desktop, migra~/.docker/config.jsonquitandocredsStoreycurrentContext, crea un backup~/.docker/config.json.docker-desktop.bakcuando hace cambios y borra~/.docker/desktop. feature_flags.virt_managerusadisabledpor defecto; cuando lo activas instala libvirt, QEMU y virt-manager, arrancalibvirtd, añade el usuario objetivo a los gruposlibvirtykvm, y fijaqemu:///systemcomo URI por defecto de libvirt para la sesión de usuario.feature_flags.openvpnusaautopor defecto; cuando detectanetwork-manageren el host instala el backend mínimo de OpenVPN que NetworkManager necesita para las conexiones VPN nativas. Si el host no usa NetworkManager,autono arrastra ese stack por sorpresa; en ese caso soloenabledfuerza la instalación.feature_flags.thunderbirdusadisabledpor defecto; cuando lo activas, instalaorg.mozilla.Thunderbirdvía Flatpak.feature_flags.desktop_toolsusaautopor defecto y solo instala tooling específico de escritorio cuando detecta una base compatible.feature_flags.clip_winusaautopor defecto y convierteclip-winen el gestor de portapapeles preferido cuando no detecta otro ya instalado.feature_flags.copyqqueda como vía legacy y usadisabledpor defecto; solo conviene activarlo explícitamente si quieres seguir en CopyQ.feature_flags.office_suiteusaautopor defecto y solo instala LibreOffice si no detecta otra suite ofimática ya instalada.feature_flags.file_manager_integrationusaautopor defecto y solo habilita la integración si VS Code también está habilitado.feature_flags.git_credential_oauthmigra la autenticación HTTP(S) de Git a Git Credential Manager, instalado desde un.debupstream fijado por versión y checksum para Ubuntu y Pop!_OS.- La configuración global de Git pasa a usar
credential.helper=/usr/local/bin/git-credential-managerycredential.credentialStore=secretservice, de modo que los tokens quedan persistidos en el keyring del escritorio y sobreviven reinicios. - Si el host tiene una sesión GNOME, Pop o COSMIC y habilitas VS Code o Git Credential Manager, el playbook instala
gnome-keyringpara que exista un proveedor Secret Service/libsecret y no aparezca el warning de keyring en VS Code. - El playbook elimina
git-credential-oauthy mantiene el repositorio estable de git-core en Ubuntu y Pop!_OS para instalar una versión upstream reciente de Git, compatible con Git Credential Manager. - Los repositorios APT gestionados directamente por este repo para Microsoft, Docker y git-core usan keyrings dedicados bajo
/etc/apt/keyrings, y el flujoapt-cleanborra definiciones legacy conocidas para evitar entradas duplicadas o avisos portrusted.gpgenapt. apt_base_packagesincluyeripgrep, y el entorno de Home Manager añaderipgreppara que el comandorgexista tanto en la capa del sistema como en la del usuario.distro_flatpak_appsdefine las aplicaciones de escritorio vía Flatpak por distro, excluyendo RustDesk porque se instala de forma nativa.rustdesk_versionfija la versión de RustDesk que se descarga como paquete.deb.rustdesk_release_arch_maptraduce la arquitectura Debian detectada al sufijo usado por los artefactos oficiales de RustDesk.supported_distributions,deb_arch_mapynix_system_mapconvierten facts de Ansible en valores utilizables para APT y Nix en Ubuntu y Pop!_OS, incluyendo hosts ARM64.clipboard_manager_package_candidatesdefine qué paquetes cuentan como gestor de portapapeles existente a efectos del modoautodeclip-winy CopyQ.clip_win_versionyclip_win_release_deb_checksumsfijan la release pública detechlogycs/clip-winque se instala de forma reproducible desde GitHub Releases.office_suite_package_candidatesdefine qué paquetes cuentan como suite ofimática existente a efectos del modoautode LibreOffice.gnome_desktop_package_candidatesdefine qué paquetes se consideran evidencia de una sesión GNOME;gnome-tweakssolo se añade cuando esa base existe.gnome_secret_service_packagesdefine qué paquete aporta el backend Secret Service/libsecret para sesiones GNOME.vscode_file_manager_integrationaceptaauto,nautilus,desktop-entryodisabled.virt_manager_packagesdefine los paquetes APT que componen el stack de virtualización local.openvpn_core_packagesdefine la base mínima de OpenVPN.openvpn_network_manager_packagesdefine el backend adicional que solo se instala cuando el modoautodetectanetwork-managero cuando fuerzasfeature_flags.openvpn=enabled.virt_manager_default_uridefine la URI por defecto que usará virt-manager/libvirt en~/.config/libvirt/libvirt.conf.
Para instalar el perfil nativo de NetworkManager con los ajustes de split tunnel y split DNS validados en este host, usa:
sudo ./scripts/nm-openvpn-helper.sh install ~/Documents/farintervpn-final.nmconnection
./scripts/nm-openvpn-helper.sh up farintervpn-finalPara personalizar opciones sin tocar el baseline versionado:
- Copia
ansible/group_vars/all/override.exampleaansible/group_vars/all/override.yml. - El archivo
override.ymlqueda ignorado por Git y Ansible lo cargará automáticamente al ejecutar el playbook.
El modo auto se comporta así:
- Si
nautilusaparece en los facts de paquetes, crea el script en~/.local/share/nautilus/scripts/Open in Code. - Si
nautilusno está instalado, crea~/.local/share/applications/code-open-here.desktopcomo alternativa genérica basada en desktop entry. Esto evita asumir GNOME en Pop!_OS, pero no garantiza un menú contextual nativo en gestores como COSMIC Files.
El modo auto de clip-win se comporta así:
- Si ya está instalado
clip-win,copyqu otro gestor de portapapeles conocido comogpaste,klipper,diodon,cliphist,clipman,xfce4-clipmano un applet de portapapeles para COSMIC, no instala nada adicional. - Si no detecta ninguno, descarga e instala el
.debpúblico fijado detechlogycs/clip-win, crea el fichero~/.config/clip-win/setup.jsonque upstream usa como sentinel de first-run, crea autostart y aprovisiona el acceso a/dev/uinput. - En COSMIC además precrea la entrada de
Super+Ven el fichero de shortcuts con el mismo formato RON que usaclip-win; en GNOME/Pop!_OS intenta registrar el custom shortcut víagsettingsy libera tantotoggle-message-traycomotoggle-quick-settingscuando hay una sesión DBus disponible.
El modo legacy de CopyQ se comporta así:
- Si ya está instalado
copyqo algún gestor de portapapeles conocido comogpaste,klipper,diodon,cliphist,clipman,xfce4-clipmano un applet de portapapeles para COSMIC, no instala nada adicional. - Si no detecta ninguno y
feature_flags.clip_winestá endisabled, añadecopyqal conjunto de paquetes base.
En Pop!_OS 24.04 LTS con COSMIC, System76 no anuncia todavía un historial de portapapeles integrado por defecto en la release actual. Sí aparece como trabajo planificado en el roadmap oficial de COSMIC Epoch 2 bajo “COSMIC Clipboard Manager”, así que la detección auto contempla también nombres de paquetes plausibles del ecosistema COSMIC para evitar instalar CopyQ encima cuando esa pieza ya exista en el sistema.
El modo auto de LibreOffice se comporta así:
- Si ya está instalada una suite conocida como
libreoffice,onlyoffice-desktopeditors,calligra,abiwordognumeric, no instala nada adicional. - Si no detecta ninguna, añade
libreofficeal conjunto de paquetes base.
Las herramientas de escritorio GNOME se comportan así:
gnome-tweakssolo se instala cuando el host ya tiene una pila GNOME detectada.- Esto evita meter tooling específico de GNOME en equipos Pop!_OS que no estén usando GNOME/Nautilus como entorno principal.
- Ubuntu y Pop!_OS usan Flatpak para la mayoría de aplicaciones de escritorio de terceros; la selección se resuelve a partir de facts de Ansible y se puede diferenciar por distro sin tocar los roles.
- La instalación de Flatpak comprueba primero qué remotos y aplicaciones existen antes de añadir o instalar nada, para mantener la ejecución repetible.
- RustDesk se instala desde el
.deboficial upstream y no vía Flatpak, porque el servicio nativo de systemd es el camino necesario para acceso pre-login y reinicios limpios del host. - Docker usa
json-filecon rotación, modonon-blockingy buffer acotado para evitar crecimiento descontrolado de logs y reducir bloqueos por I/O, preservando otras claves ya presentes endaemon.jsoncomodata-root. Loslog-optsse escriben como strings porquedockerdlo exige endaemon.json. - Nix usa
nix_install_modepara controlar cómo se instala en el host. El valor por defecto essingle-user, que evita crear la batería de usuariosnixbld*en estaciones de trabajo donde no hace falta el daemon multiusuario. Si necesitas el modelo clásico con daemon y build users compartidos, cambianix_install_modeamulti-user. - En modo
multi-user, el repositorio sigue usando Determinate Systems para simplificar una instalación consistente en Ubuntu/Pop!_OS. - Home Manager se activa construyendo el paquete de activación desde el flake del sistema detectado, lo que evita depender de una arquitectura fija o de una instalación previa del ejecutable
home-manageren el host. - La activación de Home Manager usa un perfil nombrado y estable en
~/.local/state/nix/profiles/my-workstation-home-manager; Ansible actualiza ese perfil explícitamente y ejecuta el scriptactivatecon--driver-version 1para evitar que el propio activation script siga creando generaciones extra en el perfil legacyhome-manager. - El playbook
ansible/nix-clean.ymly el atajomake nix-cleanpodan generaciones antiguas del perfil nombrado actual y también de las rutas legacy conocidas de Home Manager, incluyendo~/.local/state/nix/profiles/home-manager,~/.local/state/home-manager/profiles/home-managery/nix/var/nix/profiles/per-user/$USER/home-managersi aún existen; después ejecutannix-collect-garbagepara limpiar rutas no alcanzables del store sin depender denix-command. - Si una máquina ya tiene Nix multiusuario y quieres eliminar los usuarios
nixbld*, usaansible/nix-migrate-single-user.ymlomake nix-migrate-single-user. Ese flujo desinstala la instalación multiusuario existente con/nix/nix-installer uninstall --no-confirmcuando detecta Determinate, o aplica los pasos documentados por upstream para Linux con systemd cuando no hay receipt/uninstaller, y luego vuelve a aprovisionar Nix en modosingle-user. - Home Manager también instala un timer de usuario que limpia periódicamente ficheros antiguos en
~/Downloads, aplica limpieza por antigüedad solo a directorios explícitos de herramientas sin pruning nativo claro como~/.bun/install/cache,~/.cache/cargo-target,~/.cache/go-buildy~/.cache/go/pkg/mod, y además ejecutauv cache prune,direnv pruneynix-collect-garbage --delete-older-thanpara evitar barridos agresivos sobre todo~/.cache. - Home Manager también instala wrappers
npmynpxen~/.local/binpara que Bun pueda actuar como sustituto por defecto denpmynpxen la shell del usuario. - GitHub Copilot CLI se instala de forma declarativa mediante
pkgs.github-copilot-cli, evitando instalaciones de red durante la activación de Home Manager.
DOTFILES_REPO_URLenbootstrap.shsi quieres clonar desde un fork o mirror distinto al repositorio oficial.- El tema de Oh My Zsh en
nix/home.nix. - Los wrappers
npmynpxennix/home.nixsi prefieres mantener los binarios de Node.js sin Bun como compat layer. - La política
cleanupPolicyennix/home.nixsi quieres cambiar la frecuencia o la antigüedad máxima deDownloads, los directorios explícitos con limpieza por antigüedad, o la limpieza nativa deuv,direnvy Nix. nix_home_manager_profile_nameynix_cleanup_generation_max_age_daysenansible/group_vars/all/main.ymlsi quieres renombrar el perfil estable de Home Manager o cambiar la retención que usamake nix-clean.nix_install_modeenansible/group_vars/all/main.ymlsi quieres elegir entresingle-userymulti-user. Si una máquina ya tiene Nix multiusuario instalado, el playbook falla de forma explícita cuando pidessingle-userpara que no te quedes con los usuariosnixbld*pensando que el modo cambió solo.DOTFILES_EDITORsi desactivas VS Code y quieres queEDITORyVISUALapunten a otro binario.rustdesk_versionenansible/group_vars/all/main.ymlsi quieres fijar otra release oficial de RustDesk.feature_flags.virt_manager,virt_manager_packagesyvirt_manager_default_urisi quieres ajustar el stack de virtualización local.- Los
feature_flags,distro_flatpak_appsy el modo de integración del gestor de archivos enansible/group_vars/all/main.yml. feature_flags.openvpn,openvpn_core_packagesyopenvpn_network_manager_packagessi quieres ajustar cuándo se instala el backend de OpenVPN y evitar dependencias de NetworkManager cuando no hagan falta.
Para aprovisionar solo OpenVPN y sus paquetes relacionados:
ansible-playbook ansible/local.yml --tags openvpn
./bootstrap.sh --tags openvpnPara instalar solo una feature opcional sin tocar override.yml, usa dotfiles_only_features.
El selector fuerza a enabled solo las features indicadas, desactiva el resto de features opcionales durante esa ejecución y evita incluir roles no relacionados. En una ejecución como thunderbird, el playbook ya no recorre desktop_apps, docker, virt_manager, file_manager ni nix, y tampoco instala el bundle por defecto de Flatpaks de escritorio.
Ejemplos:
ansible-playbook ansible/local.yml --extra-vars 'dotfiles_only_features=thunderbird' -K
make install-feature features=thunderbird
./bootstrap.sh --only-feature thunderbirdTambién acepta varias features separadas por comas:
make install-feature features=thunderbird,openvpn
./bootstrap.sh --only-feature thunderbird,openvpnRustDesk queda aprovisionado como paquete nativo y con el servicio rustdesk habilitado en systemd, así que tras volver a ejecutar el playbook no debería hacer falta reiniciar toda la máquina. Si el login manager sigue usando Wayland, el acceso a la pantalla de login puede seguir limitado porque upstream todavía depende de X11 para ese escenario.