├── LICENSE ├── README.md ├── etc └── pacman.d │ └── hooks │ └── 10-commit-root.hook ├── install-stateless-arch-tools.sh └── usr ├── lib └── initcpio │ ├── hooks │ └── stateless-mode-boot │ └── install │ └── stateless-mode-boot └── local └── sbin ├── base-manager ├── garbageauto ├── pac-base └── user-customize-grub-setup /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stateless Arch (transactional)

2 | 3 | **Esse é um projeto de atualizações contínuas. Se assegure de ter uma cópia recente do repositório antes de testar. As releases são unicamente para marcar a evolução do código, e não devem ser usadas** 4 | 5 | Inspirado em sistemas como o Clear Linux, Fedora SilverBlue e Suse MicroOS, decidi tentar trazer algo semelhante a eles para o ArchLinux. Essa ferramenta visa permitir que o root controlado pelo pacman seja diferente do root do sysadmin. Dessa forma, é possível descartar configurações problemáticas sem perder atualizações. E usando uma abordagem transacional, também é possível fazer atualizações em uma "nova branch" do sistema, de forma que o root atualmente em uso não é tocado. 6 | 7 | 8 | Se valendo de overlayfs, e de como é fácil adicionar tarefas ao init do ArchLinux, um script embutido no initrd se encarregará de montar /etc/, /var, /root, /mnt, /home, /opt, /srv, /usr/local com permissão de leitura e escrita sobre uma raiz read-only (inspirado pelo código de Antynea em [Grub Btrfs](https://github.com/Antynea/grub-btrfs/blob/master/initramfs/Arch%20Linux/overlay_snap_ro-hook)). 9 | 10 | É possível fazer isso sobre qualquer sistema de arquivos, porém, com btrfs, se ganha outra capacidade, como se sabe: snapshots baratos. Para os efeitos desse documento, sempre que ler branch, pense em snapshot btrfs. 11 | 12 | **Dado que o pacman envia para stdout o status da operação, e que arch-chroot é capaz de rodar comandos, e trazer seu status de saída de volta para o host, via snapshots btrfs se faz possível que a operação sempre seja feita não diretamente no root atualmente em uso, e sim em uma nova "branch" do sistema. Assim, como um git, o status da operação de "merge" dos novos pacotes define se aquela branch se tornará o novo padrão do "repositório". Se o merge for bem sucedido, a branch é promovida. Caso contrário, ela é descartada. Nenhum bit do root atualmente em uso é tocado durante uma operação de "merge", portanto, por menores que sejam as adições/modificações, se faz necessário reiniciar para usá-las.** 13 | 14 | [Se você estiver familiarizado com o funcionamento das atualizações do Opensuse Kubic/MicroOs](https://kubic.opensuse.org/documentation/transactional-update-guide/transactional-update.html), apenas lhe dizer que aqui todas as transações rodam com --continue por padrão, e voltam para current-root apenas em caso de erros críticos na manipulação de new-roots ainda não bootados bastará para ter uma ideia geral do sistema. 15 | 16 | Para quem não tem familiaridade com um sistema de arquivos com suporte a snapshots + abordagem transacional, usar termos de git para se referir ao manuseio do sistema pode tornar a comunicação mais clara. 17 | / 18 | Em Stateless-Arch transacional, adicionar e remover programas, bem como quaisquer intervenções no root verdadeiro significa: 19 | 20 | 1. checkout -b transacional main 21 | 2. modificar a branch transactional (atualização, instalação e remoção de pacotes, "merge" a partir de outro remoto, os repositórios do ArchLinux no caso) 22 | 23 | 3. se o processo de merge for bem sucedido, faça 24 | * branch -m main old-main-date-operation 25 | * branch -m transactional main 26 | * o próximo boot implica em checkout main 27 | 28 | 3. se o processo de merge for mal sucedido, faça 29 | * git branch -D transactional 30 | 31 | **Assim como num repositório, o processo de merge de novo código (no caso de um sistema, adição/remoção de programas) ser bem sucedido NÃO IMPLICA em um perfeito funcionamento posterior do código em si. Mas usando uma abordagem transacional, o sysadmin sempre terá um root de estado conhecido para o qual voltar (branch -m main broken-main && checkout -b main old-main-date-operation).** 32 | 33 | 34 | # Implementação

35 | 36 | implementar Stateless Arch em uma instalação nova é simples como: 37 | 38 | * pacstrap em um único subvolume btrfs (/boot incluso). Deve constar nos pacotes, arch-install-scripts grub grub-btrfs bash e git; 39 | * arch-chroot no subvolume; 40 | * passwd; 41 | * gerar locales; 42 | * git clone desse repositório(pode ser em /tmp); 43 | * executar o scritp install-stateless-arch-tools.sh 44 | * seguir as instruções finais do scritp (somente operações normais em qualquer instalação do ArchLinux) 45 | * reiniciar 46 | 47 | (é possível implementar numa instalação existente, mas os passos necessários mudam conforme o ponto de partida; deixo para você a tarefa de descobrir quais passos são esses :wink:) 48 | 49 | # Arquitetura

50 | 51 | Ao concluir o boot, a raiz consistirá em duas camadas, sendo: 52 | 53 | **Primeira camada: PacmanRoot**: um subvolume btrfs, com permissão somente leitura, onde está instalado o ArchLinux, com todas as pastas do root, **incluindo** /boot (obviamente /boot/efi será um ponto de montagem para fat32 EFI durante a instalação da grub, se efi). Esse root pode inicialmente possuir configurações mínimas, somente senha root, locales, e os arquivos e modificações necessárias para que Stateless Arch funcione. O próprio fstab não precisa ficar aqui, sua edição durante a instalação do sistema pode ser ignorada. Em todo boot de uma instalação com Stateless-Arch transacional, o PacmanRoot terá sua permissão de escrita trocada para false. 54 | 55 | 56 | **Segunda camada: Sysadmin** um subvolume btrfs com permissão de leitura e escrita, que conterá diretórios para permitir montagem overlay com permissão de escrita em /etc/, /var, /root, /mnt, /home, /opt, /srv, /usr/local/, acima da camada somente leitura anterior. Assim, configurações de serviços, montagem, udev e afins podem ser honradas apropriadamente pelo systemd, na fase 2 da inicialização, e scripts customizados relacionados á suspensão e desligamento podem ser criados livremente (devem ser criados em /etc/system/ uma vez que /usr/lib/systemd é somente leitura. Basta criar as pastas correspondentes, e tudo funcionará de acordo). O subvolume que abriga os overlays tem o nome e o tipo de compressão explicitamente declarados no init; renomear o subvolume sem mudá-lo em /usr/lib/initcpio/hooks/stateless-mode-boot e reconstruir o init implica em um boot quebrado. Esse subvolume retem o estado do sistema, e pode ser simplesmente descartado (ou renomeado). **Desde que um novo seja criado**, no boot seguinte o scritp no initrd se encarregará de criar os diretórios necessários para essa camada. O sistema iniciará então no branch mais recente de PacmanRoot, mas sem as configurações do sysadmin. Um usuário com experiência mínima em btrfs pode fazer essa operação manualmente de forma trivial, mas isso não é necessário: base-manager --reset-sysadmin-data interme 57 | dia essa operação de forma simples. 58 | 59 | **ATENÇÃO: conforme explicado no script de implementação, o hook que torna isso possível deve ser o último em HOOKS no /etc/mkinitcpio.conf, é compatível com os hooks ativos por padrão no ArchLinux, e NÃO é compatível com os hooks grub-btrfs-overlayfs e systemd; a combinação com outros hooks não foi testada** 60 | 61 | # Sobre pontos de montagem e serviços

62 | 63 | Ainda que não seja necessária a presença de PacmanRoot no fstab para o sucesso do boot, é uma boa prática que ele esteja lá. Pelo menos nos meus testes, quando ele não está presente, opções de montagem referentes a compressão de todos os subvolumes do mesmo dispositivo de bloco não são honradas. Então tenha sim / no fstab, apenas por esse motivo. Se não usar compressão, pode ignorar esse aviso. 64 | 65 | **É uma boa prática existir uma montagem verdadeira para /home/$USER no fstab do sysadmin**, que será montada sobre o overlay de /home. Ferramentas de gerenciamento de container (docker/podman) não funcionam corretamente quando seu armazenamento é um overlay. Crie um subvolume/partição para a home de cada usuário da máquina, e os coloque corretamente no fstab. O mesmo pode ser verdade (não testado) para bancos de dados e imagens de máquinas virtuais nos diretórios aninhados em /var. Se usa algumas dessas coisas no dia a dia, e precisa que fiquem na hierarquia de /var, tenha partições e subvolumes verdadeiros para montar apropriadamente. Enfim, teste suas montagens antes de migrar totalmente para Stateless Arch, e verifique se quaisquer inconsistências encontradas podem ser resolvidas criando um ponto de montagem dedicado. 66 | 67 | # Usabilidade

68 | 69 | Para usar um ArchLinux com Stateless Arch, o sysadmin deve aceitar e conviver com algumas limitações e mudanças de usabilidade: 70 | 71 | * atualização e remoção de pacotes somente de forma mediada por pac-base, não diretamento pelo pacman(discutido a seguir), e precisando reiniciar para ter acesso às modificações; 72 | 73 | * como já deu para perceber, grub como bootloader é uma exigencia aqui. Faço isso para poder incluir o próprio kernel nos branchs. Dado que a grub consegue lidar com kernel e initrd sob btrfs, comprimido ou não, seja em legacy ou em efi, se torna uma ferramenta com um fator social e até mesmo ambiental importante : hardware sem capacidade de boot efi continua sendo suportado, e ao ter toda a raiz inclusa em branchs, a recuperação de uma atualização problemática, ou mesmo um reset total não passa por mais carga de acesso aos repositórios para baixar iso e pacotes. Mesmo implementar o ArchLinux em outra máquina se torna fácil como um btrfs send via ssh de seu último branch, com a certeza que isso não incluirá chaves ssh,configurações de sysadmins e grupos, pontos de acesso wifi, ou outras configurações sensíveis. PacmanRoot está sempre em "estado de pacstrap", ou muito perto disso. 74 | 75 | 76 | * a geração de locale-gen deve ser incluída diretamente na raiz, como já citado no processo de implementação, o que pode ser inconveniente caso o sysadmin troque constantemente de idioma; editar a raiz diretamente será discutido a seguir. Uma alternativa pode ser, durante a instalação do sistema, antes de implementar Stateless Arch, descomentar todos os locales em /etc/locale.gen, e gerar todos. 77 | 78 | * Se valer primariamente de flatpak, appimage, ou, minha alternativa preferida, o excelente [Distrobox](https://github.com/89luca89/distrobox) de 89luca89. Dado que tanto /var quando a home do usuario são separados (ver considerações na sessão sobre montagens), voltar branchs da raiz não implica em perder acesso a nenhum desses programas. Delegue á base somente o suficiente para subir o modo gráfico, drivers em geral, suporte a hardware, virtualizadores, o suporte a containers ,e outras ferrramentas que dependam de alto nivel de acesso, como por exemplo particionadores de disco (dica, tanto o [Podman](https://github.com/89luca89/distrobox/blob/main/docs/compatibility.md#install-podman-in-a-static-manner) quanto o [Docker](https://github.com/vmath3us/guiadevopsbrasil/blob/main/dicas/linux/docker-sem-root.md) podem ser instalados direto na home, sem passar pelo gerenciamento de pacotes do sistema, ficando assim imunes a restaurações de sistema, e usados rootless). Mesmo programas de edição de som são plenamente usáveis de dentro de um container (testado usando pipewire e wireplumber). O próprio DistroBox pode ser instalado na home de usuário. Os ícones de desktop de flatpaks, appimages e exportados via Distrobox surgem normalmente em sua área de trabalho, o funcionamento é totalmente transparente. E com distrobox é possível usar pacotes de outras distribuições, não somente do ArchLinux (eu tenho a leve impressão que a maior parte dos usuários de Stateless Arch usará Alpine como imagem padrão do Distrobox sempre que possível). [Na verdade, você até mesmo não instalar a sessão gráfica no root, e sim dentro de um container, de forma a ter uma sessão de usuário inteiramente segura, de onde não é possível usar comandos perigosos como dd, e ainda assim, instalar e remover pacotes normalmente.](https://github.com/89luca89/distrobox/blob/main/docs/posts/run_latest_gnome_kde_on_distrobox.md) Para uma sessão Gnome mínima no ArchLinux no Distrobox, basta os pacotes gnome-shell, gnome-session, e gnome-control-center.(PS.: o suporte a rede e a som deve ser instalado e iniciado pelo usuário real no root real, e a partir daí ele será passado para o "container de sessão" de forma transparente, permitindo parear dispositivos bluetooth, ou adicionar novas redes wifi, e usar o som normalmente. O uso de gdm no host como gestor de login é altamente recomendado). 79 | 80 | # Manutenção 81 | 82 | Os scripts base-manager e pac-base serão salvos em /usr/local/sbin, de forma que uma edição do sysadmin em seu próprio overlay valerá para alterar quaisquer parâmetros que queira. **Isso NÃO é verdadeiro para o hook do init.** 83 | 84 | Base-manager acumula algumas funções, uma delas foi citada acima, as demais serão discutidas brevemente abaixo; veja em detalhes clonando esse repositório, e executando base-manager --help (uma das funções). 85 | 86 | Atualizações e manuseio de programas são possíveis usando pac-base, seguido da cli normal do pacman (ex: pac-base -Syu). Pac-base criará uma nova branch do sistema (transacional) a partir da branch padrão, montará diretamente, e por cima dele uma montagem bind de /var/cache/pacman/pkg, /etc/mkinitcpio.conf,/etc/mkinitcpio.d./etc/modprobe.d, /etc/pacman.d, /etc/pacman.conf, /usr/local do sysadmin, e em seguida, provido por arch-install-scripts, executará "arch-chroot pacman" exportando os comandos passados para pac-base. O pacman no ambiente chroot executará a transação. Em caso de sucesso, pac-base receberá essa informação, e então irá tornar a branch padrão em uma branch secundária, e a branch transacional como padrão, usando para isso simples mudanças de nome das branchs, e atualização de bootloader (grub), montando sobre a nova branch main, via bind, /etc/default/grub, /etc/default/grub-btrfs, e /etc/grub.d do sysadmin. Em caso de falha do pacman, a branch padrão mantém seu status. Cancelar a operação manualmente via ctrl-c, ou respondendo não ao pacman é considerado uma falha, e será tratado como tal. 87 | 88 | A atualização do grub.cfg é possivel a partir de base-manager --bootloader-update, e não diretamente pelo grub-mkconfig. Edite /etc/default/grub normalmente em seu overlay, invoque base-manager, e ele cuidará do resto, também fazendo a operação em uma branch transacional e validando a saída da grub. É **fortemente recomendado** que ao receber atualizações do pacote grub, ela seja REINSTALADA (grub-install ...), ANTES do próximo boot. Não é possível que Stateless Arch automarize esse processo, dado que cada usuário pode usar a grub de uma forma, em disco diferente do root por exemplo, ou com automações ligadas a secure-boot. Mas já que /etc/pacman.d/hooks é montado sobre PacmanRoot por pac-base, você poderá automatizar de acordo com sua realidade específica o processo de reinstalação da grub ao receber um novo pacote dela. [Leia este link sobre o assunto](https://lists.gnu.org/archive/html/grub-devel/2022-08/msg00381.html), além da archwiki a respeito da grub. Existe um hook preparado, bem como um scritp simples atrelado à pac-base, mas que só irão funcionar após edição manual do sysadmin. 89 | 90 | Base-manager --restore-root provê uma forma simples de tornar qualquer dos branchs disponíveis em PacmanRoot a partir do boot seguinte; é uma operação não destrutiva, as branchs são somente duplicadas e renomeadas. 91 | 92 | Com base-manager --edit-pacmanroot, um branch transacional será criado, montado, e plenamente acessível e manuseável conforme o sysadmin desejar, via chroot. Os mesmos binds de pac-base serão montados aqui também. Após saír do chroot, a branch padrão será renomeada, e a branch transacional será tornada como padrão. O sysadmin deve reiniciar e conferir se suas modificações foram bem sucedidas. Em caso contrário, basta usar --restore-root para reverter. 93 | 94 | Para editar PacmanRoot sem nenhuma montagem bind, basta, após base-manager --edit-pacmanroot, desmontá-las. Tenha em mente que, caso use o pacman nessa situação, se a cache não for limpa, dali por diante ela será propagada em todas as novas branchs, assim como as modificações. Além disso, no processo de atualizar a grub, todas as montagens bind serão refeitas, portando editar /etc/grub.d e /etc/default/grub diretamente de PacmanRoot (e não nas montagens bind) é inútil. 95 | 96 | Por sua vez, base-manager --reset-sysadmin-data irá mover o overlay de sysadmin para uma branch, e criar uma nova, que irá entrar em vigor no boot seguinte. Assim, o estado do sistema passa a ser o que está diretamente em PacmanRoot; caso queira somente algumas das configurações presentes no overlay de sysadmin anterior, basta montá-lo, e copiar os arquivos desejados normalmente. 97 | 98 | Base-manager e pac-base por padrão não fazem nenhuma operação destrutiva (sendo scritps simples, seu comportamento pode ser alterado se o sysadmin assim desejar), e buscam ao máximo tratar erros de forma a não deixar o sysadmin sem uma branch main a ser usada no boot seguinte. Por vezes, isso implica em voltar muitas branchs, e tornar o root **atualmente em uso** como upstream, ignorando quantos sejam os branchs à frente que já existam. Exemplo, supondo uma máquina que não é reiniciada a um mês, que foi atualizada a cada 3 dias (via timer rodando pac-base -Syu --noconfirm), gerando 10 novas branchs, caso ocorra um erro na 11ª atualização, a correção de erros de base-manager/pac-base tentará tornar como upstream a branch anterior em que a atualização foi bem sucedida (10ª). Caso isso também falhe, base-manager-/pac-base tentará promover a branch que deu boot na máquina, por considerá-la confiável, e portando ignorando todos os updates subsequentes, sem excluí-los. Uma vez que o timer continue rodando, na 12ª atualização (dia 36), ele tentará aplicar todas as atualizações perdidas numa única nova branch. Leve isso em conta ao automatizar o processo de atualização. Ao perceber que um erro desse tipo ocorreu, confira o dmesg; um erro na geração em si de novas branchs pode indicar problemas na saúde do sistema de arquivos. 99 | 100 | Será papel do sysadmin implementar quaisquer políticas que queira de garbage collector dos branchs. No meu uso pessoal, um temporizador systemd roda um script bash a cada 15 dias, e deixa os 20 branchs mais recentes. Outra possibilidade é incluir o garbage collector diretamente em pac-base, de forma que o número de branchs permaneça sempre o mesmo, descartando o branch mais antigo após uma transação bem sucedida, e antes de atualizar o bootloader. Códigos de exemplos serão copiados durante a instalação de Stateless-Arch, mas não serão ativos por padrão. 101 | 102 | # Considerações finais 103 | 104 | Um leitor atento já percebeu que a ideia aqui é que PacmanRoot permaneça sempre em "estado de pacstrap": Qualquer nova branch terá somente pacotes do pacman, em seus padrões, somado à pouca configuração (senha root e locales) de /etc geradas durante a instalação; faça todo o resto no overlay do sysadmin, e na sua home, e você poderá enviar um branch de PacmanRoot para outra pessoa/dispositivo ( usando btrfs send/receive, tar, rsycn, ou que for), com a certeza de não enviar junto chaves ssh, senhas de wifi, ou outras informações sensíveis; use base-manager --reset-sysadmin-data, e no boot seguinte o sistema retornará em "modo de fábrica". Outro caso de uso seria uma abordagem semelhante a [Erase your darlings](https://grahamc.com/blog/erase-your-darlings), onde se embute, direto em PacmanRoot, configurações de root consideradas ótimas, e em todo boot, o initrd recria um overlay de sysadmin limpo. Ou ainda, se estabelece um sysadmin-overlay que deve ser sempre restaurado para um estado conhecido no boot, e ainda assim, pode ser limpo. É fácil converter Stateless Arch para esse propósito (dica, só precisa de duas linhas a mais no initrd, e algumas poucas remoções em base-manager e pac-base), mas deixo essa tarefa para quem se interessar por esse caso de uso. 105 | 106 | O sistema dessa forma será altamente resiliente. De fato, excetuando algo que afete diretamente o sistema de arquivos, ou apagar as imagens da grub (mbr do disco se disco mbr+legacy, partição biosboot se gpt+legacy, arquivos da partição fat-32 se efi), o sistema é facilmente recuperável em praticamente qualquer situação sem necessidade de live-boot. Novo kernel/driver de vídeo problemático? Use base-manager --restore-root em um branch anterior. A grub não encontrou o arquivo de configuração e caiu no shell? Use a cli para chamar o configfile de qualquer um dos branchs, todos eles terão um grub.cfg. Grub-rescue? Chame o binário da grub de qualquer um dos branchs, e você terá o grub-shell completo, se onde será possível chamar o grub.cfg de qualquer um dos branchs. 107 | 108 | Caso o sysadmin regrida para um branch onde não exista um determinado binário, mas em seu /etc overlay exista uma configuração de serviço que aponte para esse binário, é possível que o boot seja parado. Isso não implica em um branch de PacmanRoot quebrado, somente em uma configuração de serviço do sysadmin que não pode ser honrada. Esse gerenciamento é totalmente delegado ao sysadmin. Em alguns casos, o shell de emergência do boot pode bastar para remover a inconsistência encontrada e permitir que o boot prossiga. Caso contrário, tente iniciar o sistema em branchs anteriores do root. Caso seja impossível estabelecer qual a causa verdadeira do problema rapidamente, o sysadmin pode simplesmente usar base-manager --reset-sysadmin-data a partir do shell de emergência de qualquer branch, que todo o overlay do sysadmin será renomeado (para inspeção futura), e um novo será gerado. Como já dito, deletar o sysadmin overlay é responsabilidade do sysadmin. Se o boot, por qualquer motivo que seja, ficar parado no initrd, é possível a partir do shell dele, fazer manualmente a mesma operação que --reset-sysadmin-data. 109 | 110 | Repare que esse projeto se destina a permitir um sistema confiável, mas que ainda assim, seja humanamente modificável e gerenciável, de forma relativamente familiar. Opensuse MicroOS, Fedora SilverBlue e outras, alteram tanto a hierarquia do sistema de arquivos, quanto gerenciadores de pacotes, além dos pacotes em si de seus repositórios, de forma a automatizar muitas das tarefas que nesse projeto são delegadas ás mãos do sysadmin; se você quer um sistema inteiramente autogerenciado, com garantias de funcionalidade, mas não amigável a humanos, vá diretamente para uma das alternativas acima. Stateless Arch é para usuários de ArchLinux que querem desfrutar das vantagens de um sistema sem estado e imutável, mas não abrem mão de conseguir customizar seu sistema manualmente, com pouquíssimo atrito, sem sentir que estão lutando contra o sistema. **Sempre lembrando que, grandes poderes...**. 111 | 112 | Assim como no Suse MicroOS, e em qualquer sistema desse tipo, o sistema não é à prova de um sysadmin com nível de acesso root verdadeiro (e não de dentro de um container) que QUEIRA quebrar o sistema. Exemplos simples: troque o nome do subvolume root no Suse MicroOS, e reinicie, e o boot parará no init. Apague a configuração de boot do Clear Linux, e algo parecido ocorrerá. Apague grub.cfg do Fedora Silverblue, e se depare com grub-shell. Em qualquer que seja o sistema, um dd de dev/zero sobre o root o destrói, obviamente. Portanto, não se trata de desafiar o sysadmin a conseguir quebrar uma instalação, e sim de dificultar ao máximo que um sysadmin que quer MANTER uma instalação funcional a perca, e auxiliá-lo a replicar a instalação se necessário. 113 | 114 | O uso de Stateles Arch (transacional) da forma em que está nesse momento já é possível , mas se trata de uma ferramenta beta. Mesmo quando for terminada, **NÃO SERÁ** indicada para usuários inexperientes. Problemas que exijam conhecimento de pontos de montagem, manipulação do processo de boot e de subvolumes btrfs podem surgir. 115 | 116 | **Podem haver problemas e incompatibilidades que eu não encontrei nos meus testes, e que podem aparecer somente com o uso de determinados programas, ou combinação de programas, ou cenários especiais.** 117 | 118 | **A máquina é sua, o sistema de arquivos é seu, a decisão de usar esses scripts foi sua, portanto os riscos e prejuízos são seus.** 119 | 120 | **O suporte a luks e a secure-boot não foi testado.** 121 | 122 | Para construir rapidamente um setup Stateless Arch focado em utilização de containers (semelhante ao Suse MicroOs e ao Fedora Silverblue), visite [Arch Start](https://github.com/vmath3us/arch-start). Lá estará um espelho da minha própria máquina, de forma que, de posse daquele repositório e desse, minha instalação é reproduzível. 123 | 124 | Para um vídeo demonstrando instalação e manuseio do sistema, [assista aqui](https://youtu.be/8xyABDJVDTQ) 125 | 126 | Para imagens de máquina virtual, acesse [Stateless Arch no Telegram](https://t.me/StatelessArch) (após o primeiro boot, clone esse repositório, e cole manualmente os scritps em seus respectivos locais, para garantir que estejam na versão mais recente) 127 | -------------------------------------------------------------------------------- /etc/pacman.d/hooks/10-commit-root.hook: -------------------------------------------------------------------------------- 1 | [Trigger] 2 | Operation = Install 3 | Operation = Upgrade 4 | Type = Package 5 | Target= grub 6 | [Action] 7 | Description = reinstall grub after upgrade 8 | When = PostTransaction 9 | Exec = /usr/local/sbin/create-log-grub 10 | AbortOnFail 11 | -------------------------------------------------------------------------------- /install-stateless-arch-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ####################################--initial-vars--################################################################ 3 | rootblock=$(grub-probe / --target=device) 4 | rootfilesystem=$(grub-probe /) 5 | subvol_to_move=$(grub-mkrelpath /) 6 | toplevel_dir=$(mktemp -d -p /tmp) 7 | #####################--change-here-and-in-all-files-usr/local/sbin--########################## 8 | default_root="@base_system" 9 | #####################--change-here-and-in-usr/lib/inictpio/hooks/stateless-mode-boot--########################## 10 | default_sysadmin_data="@sysadmin_state" 11 | ############################################################################################################# 12 | function welcome (){ 13 | printf " 14 | ############################################################################################### 15 | ############################################################################################### 16 | Stateless-Arch 17 | ############################################################################################### 18 | ############################################################################################### 19 | 20 | " 21 | check_user 22 | } 23 | function check_user (){ 24 | user=$(whoami) 25 | if [ "$user" != "root" ] ; then 26 | printf " 27 | execute como root. Saindo com status de erro 28 | 29 | " &&\ 30 | exit 1 31 | else 32 | check_filesystem 33 | fi 34 | } 35 | function check_filesystem(){ 36 | umount /boot/efi 37 | umount /boot 38 | if [ $? -eq 32 ] ; then 39 | if [ "$rootfilesystem" != "btrfs" ] || [ "$subvol_to_move" == "$nonevalue" ]; then 40 | printf " 41 | use somente em um root inteiramente btrfs, dentro de um subvolume. Saindo com status de erro 42 | " 43 | exit 1 44 | else 45 | printf " 46 | sistema de arquivos conferido, testando dependencias 47 | " &&\ 48 | check_deps 49 | fi 50 | else 51 | printf " 52 | use a raiz inteira, em um único subvolume btrfs. /boot separado incompatível. Saindo com status de erro" 53 | exit 1 54 | fi 55 | } 56 | function check_deps (){ 57 | if [ -f /etc/grub.d/41_snapshots-btrfs ] && command -v grub-install && command -v arch-chroot ; then 58 | printf " 59 | dependencias conferidas, adaptando arquivos 60 | " &&\ 61 | last_chance 62 | else 63 | printf " 64 | alguma das dependências não foi satisfeita. 65 | verifique sua instalação 66 | essa ferramenta precisa de 67 | grub 68 | grub-btrfs 69 | arch-install-scripts 70 | saindo com status de erro 71 | 72 | " 73 | exit 1 74 | fi 75 | } 76 | function last_chance (){ 77 | time=15 78 | sleep 1s 79 | while [ $time -ge 1 ] ; do 80 | printf " 81 | 82 | ############################################################################################### 83 | ############################################################################################### 84 | Stateless-Arch 85 | ############################################################################################### 86 | ############################################################################################### 87 | 88 | " 89 | echo "iniciando manipulação de subvolumes e propagação de arquivos em $time segundos, ctrl-c para cancelar" 90 | sleep 1s 91 | let "time--" 92 | done 93 | mount_device_and_manage_subvols 94 | } 95 | 96 | function mount_device_and_manage_subvols(){ 97 | echo "limpando cache do pacstrap..." 98 | rm -rf /var/cache/pacman/pkg/* &&\ 99 | mount $rootblock -o "subvolid="5 $toplevel_dir &&\ 100 | moment=$(date +%Y-%m-%d--%H-%M-%S) 101 | btrfs su snap $toplevel_dir/$subvol_to_move $toplevel_dir/@root-pre-stateless-in--$moment &&\ 102 | mv $toplevel_dir/$subvol_to_move $toplevel_dir/$default_root &&\ 103 | btrfs filesystem sync $toplevel_dir &&\ 104 | if [ $? -eq 0 ] ; then 105 | btrfs filesystem sync $toplevel_dir &&\ 106 | copy_scripts_to_root 107 | else 108 | printf " 109 | um erro na manipulação dos subvolumes ocorreu, saindo com status de erro. 110 | Verique suas alterações no cabeçalho do scritp de instalação, ou por colisão entre 111 | os nomes aqui usados e seus subvolumes já existentes 112 | " &&\ 113 | exit 1 114 | fi 115 | } 116 | function copy_scripts_to_root(){ 117 | cp usr/local/sbin/base-manager /usr/local/sbin/base-manager &&\ 118 | cp usr/local/sbin/pac-base /usr/local/sbin/pac-base &&\ 119 | cp usr/local/sbin/garbageauto /usr/local/sbin/garbageauto &&\ 120 | cp usr/local/sbin/user-customize-grub-setup /usr/local/sbin/user-customize-grub-setup &&\ 121 | cp etc/pacman.d/hooks/10-commit-root.hook /etc/pacman.d/hooks/10-commit-root.hook &&\ 122 | cp usr/lib/initcpio/hooks/stateless-mode-boot /usr/lib/initcpio/hooks/stateless-mode-boot &&\ 123 | cp usr/lib/initcpio/install/stateless-mode-boot /usr/lib/initcpio/install/stateless-mode-boot &&\ 124 | chmod a+x /usr/local/sbin/base-manager &&\ 125 | chmod a+x /usr/local/sbin/pac-base &&\ 126 | chmod a+x /usr/local/sbin/user-customize-grub-setup &&\ 127 | chmod a+x /usr/lib/initcpio/hooks/stateless-mode-boot &&\ 128 | chmod a+x /usr/lib/initcpio/install/stateless-mode-boot &&\ 129 | end_implementation || printf " 130 | os scripts de implementação não estão nos locais corretos. Clone o repositório novamente, 131 | ou edite o script de instalação para refletir corretamente suas mudanças. Saindo com status de erro 132 | " 133 | 134 | } 135 | function end_implementation (){ 136 | moment=$(date +%Y-%m-%d--%H-%M-%S) &&\ 137 | btrfs su snap -r $toplevel_dir/$default_root $toplevel_dir/@root-pos-stateless-in-$moment &&\ 138 | btrfs su cr $toplevel_dir/$default_sysadmin_data; err=$? &&\ 139 | if [ $err -eq 0 ] ; then 140 | btrfs filesystem sync $toplevel_dir &&\ 141 | umount -Rv $toplevel_dir &&\ 142 | printf " 143 | O sistema de arquivos foi preparado, e os scripts estão nos locais e com as permissões corretas 144 | edite /etc/mkinitcpio.conf, colocando AO FINAL, como ULTIMO HOOK, stateless-mode-boot. (ler README para incompatibilidades) 145 | Regere o init com mkinitcpio -P 146 | Em seguida, (se efi), monte sua partição efi em /boot/efi, 147 | INSTALE e ATUALIZE a grub e reinicie. 148 | Para iniciar sem stateless-mode-boot, aperte c no menu de boot, 149 | adicione, ao final da linha do kernel 150 | disablehooks=stateless-boot-mode, e aperte F10 151 | 152 | Se assegure de ter lido E COMPREENDIDO completamente o README 153 | 154 | Bem vindo ao Stateles Arch 155 | 156 | " && 157 | exit $err 158 | 159 | else 160 | printf " 161 | um erro na manipulação dos subvolumes ocorreu, saindo com status de erro. 162 | Verique suas alterações no cabeçalho do scritp de instalação, ou por colisão entre 163 | os nomes aqui usados e seus subvolumes já existentes 164 | " && 165 | exit $err 166 | fi 167 | } 168 | welcome 169 | -------------------------------------------------------------------------------- /usr/lib/initcpio/hooks/stateless-mode-boot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ash 2 | 3 | run_latehook() { 4 | 5 | local sysadmin_state_subvol="@sysadmin_state" ########## change here and all scritps in /usr/local/sbin 6 | 7 | local root_mnt="/new_root" 8 | 9 | local lower_dir_etc="/new_root/etc" 10 | 11 | local lower_dir_home="/new_root/home" 12 | 13 | local lower_dir_var="/new_root/var" 14 | 15 | local lower_dir_vartmp="/new_root/var/tmp" 16 | 17 | local lower_dir_roothome="/new_root/root" 18 | 19 | local lower_dir_usrlocal="/new_root/usr/local" 20 | 21 | local lower_dir_mnt="/new_root/mnt" 22 | 23 | local lower_dir_opt="/new_root/opt" 24 | 25 | local lower_dir_srv="/new_root/srv" 26 | 27 | local real_block_device=$(resolve_device "$root"); 28 | 29 | local root_overlay_protect=$(mktemp -d -p /) 30 | 31 | 32 | btrfs property set -ts ${root_mnt} ro true && ### set read-only in stateless-arch transactional 33 | 34 | 35 | local sysadmin_overlay=$(mktemp -d -p /) 36 | 37 | 38 | mount "${real_block_device}" -t btrfs -o "compress-force="zstd,subvol=${sysadmin_state_subvol} ${sysadmin_overlay} && 39 | mkdir -p ${sysadmin_overlay}/etc -v && 40 | mkdir -p ${sysadmin_overlay}/home -v && 41 | mkdir -p ${sysadmin_overlay}/var -v && 42 | mkdir -p ${sysadmin_overlay}/roothome -v && 43 | mkdir -p ${sysadmin_overlay}/usrlocal -v && 44 | mkdir -p ${sysadmin_overlay}/mnt -v && 45 | mkdir -p ${sysadmin_overlay}/opt -v && 46 | mkdir -p ${sysadmin_overlay}/srv -v && 47 | mkdir -p ${sysadmin_overlay}/work_etc -v && 48 | mkdir -p ${sysadmin_overlay}/work_home -v && 49 | mkdir -p ${sysadmin_overlay}/work_var -v && 50 | mkdir -p ${sysadmin_overlay}/work_roothome -v && 51 | mkdir -p ${sysadmin_overlay}/work_usrlocal -v && 52 | mkdir -p ${sysadmin_overlay}/work_mnt -v && 53 | mkdir -p ${sysadmin_overlay}/work_opt -v && 54 | mkdir -p ${sysadmin_overlay}/work_srv -v && 55 | 56 | 57 | mount -t overlay overlay -o lowerdir=${lower_dir_etc},upperdir=${sysadmin_overlay}/etc,workdir=${sysadmin_overlay}/work_etc,index=off,metacopy=off ${root_mnt}/etc && 58 | mount -t overlay overlay -o lowerdir=${lower_dir_var},upperdir=${sysadmin_overlay}/var,workdir=${sysadmin_overlay}/work_var,index=off,metacopy=off ${root_mnt}/var && 59 | mount -t overlay overlay -o lowerdir=${lower_dir_roothome},upperdir=${sysadmin_overlay}/roothome,workdir=${sysadmin_overlay}/work_roothome,index=off,metacopy=off ${root_mnt}/root && 60 | mount -t overlay overlay -o lowerdir=${lower_dir_usrlocal},upperdir=${sysadmin_overlay}/usrlocal,workdir=${sysadmin_overlay}/work_usrlocal,index=off,metacopy=off ${root_mnt}/usr/local && 61 | mount -t overlay overlay -o lowerdir=${lower_dir_mnt},upperdir=${sysadmin_overlay}/mnt,workdir=${sysadmin_overlay}/work_mnt,index=off,metacopy=off ${root_mnt}/mnt && 62 | mount -t overlay overlay -o lowerdir=${lower_dir_opt},upperdir=${sysadmin_overlay}/opt,workdir=${sysadmin_overlay}/work_opt,index=off,metacopy=off ${root_mnt}/opt && 63 | mount -t overlay overlay -o lowerdir=${lower_dir_srv},upperdir=${sysadmin_overlay}/srv,workdir=${sysadmin_overlay}/work_srv,index=off,metacopy=off ${root_mnt}/srv #&& ##################### remove && to disable home overlay 64 | #mount -t overlay overlay -o lowerdir=${lower_dir_home},upperdir=${sysadmin_overlay}/home,workdir=${sysadmin_overlay}/work_home,index=off,metacopy=off ${root_mnt}/home ####################### comment to disable home overlay 65 | } 66 | -------------------------------------------------------------------------------- /usr/lib/initcpio/install/stateless-mode-boot: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | build() { 4 | add_module btrfs 5 | add_module overlay 6 | add_binary btrfs 7 | add_binary btrfsck 8 | add_binary blkid 9 | add_runscript 10 | } 11 | 12 | help() { 13 | cat < mount -av && su - (você será perguntado sobre qual user) 494 | # Ao sair, tudo é desmontado. 495 | # Dado que a branch upstream é somente leitura, o uso dessa função não implica em uma nova branch. 496 | # ############################################################################################## 497 | # Só use isso se não puder evitar, teste gerar um container do ArchLinux via Distrobox, 498 | # e instalar o que precisa dentro dele. 499 | # ############################################################################################### 500 | # 501 | #" 502 | #} 503 | #function find_user(){ 504 | # read -p "digite o nome do usuário a ser usado (deixe em branco para root): " username 505 | # use_now 506 | #} 507 | #function use_now(){ 508 | # mount $block_device_root $transactional_dir -o "subvol="$default_root && 509 | # mount --bind /etc $transactional_dir/etc &&\ 510 | # mount --bind /var $transactional_dir/var &&\ 511 | # mount --bind /root $transactional_dir/root &&\ 512 | # mount --bind /srv $transactional_dir/srv &&\ 513 | # mount --bind /opt $transactional_dir/opt &&\ 514 | # mount --bind /usr/lib/systemd $transactional_dir/usr/lib/systemd &&\ 515 | # mount --bind "/usr/local" $transactional_dir/"usr/local" &&\ 516 | # mount --bind /home $transactional_dir/home &&\ 517 | # use_now_chroot 518 | #} 519 | #function use_now_chroot(){ 520 | # arch-chroot $transactional_dir mount -av && su - $username 521 | # clear_dir 522 | #} 523 | ######################################################################################################################## 524 | ######################################################################################################################## 525 | ######################################################################################################################## 526 | ##############################################--start-menu-and-asks--################################################### 527 | ######################################################################################################################## 528 | ######################################################################################################################## 529 | ######################################################################################################################## 530 | function terms_user_base_manager(){ 531 | read -p "compreendo e desejo prosseguir (enter para prosseguir, ctrl-c para cancelar):" terms_use 532 | case $terms_use in 533 | *) 534 | type_operation_select 535 | ;; 536 | esac 537 | 538 | } 539 | ####################################################################################################################### 540 | case $@ in 541 | --help) 542 | help_global 543 | ;; 544 | --bootloader-update) 545 | menu_select=$@ 546 | clear 547 | stateless_arch_welcome 548 | help_bootloader_update 549 | terms_user_base_manager 550 | ;; 551 | --bootloader-update-pos-garbage) ####################### entrypoint for garbage-collector 552 | menu_select="--bootloader-update" 553 | type_operation_select 554 | ;; 555 | --restore-root) 556 | reason="manual" 557 | menu_select=$@ 558 | clear 559 | stateless_arch_welcome 560 | help_restore_root 561 | terms_user_base_manager 562 | ;; 563 | --restore-root-pacman) ########################## entrypoint for emergency-mode pac-base 564 | menu_select=$@ 565 | id_to_restore=$id_to_restore 566 | reason=$reason 567 | type_operation_select 568 | ;; 569 | --restore-root-no-stateless) 570 | reason="prestateless" 571 | menu_select=$@ 572 | clear 573 | stateless_arch_welcome 574 | help_restore_root 575 | terms_user_base_manager 576 | ;; 577 | --reset-sysadmin-data) 578 | menu_select=$@ 579 | clear 580 | stateless_arch_welcome 581 | help_reset_sysadmin_data 582 | terms_user_base_manager 583 | ;; 584 | --edit-pacmanroot) 585 | menu_select=$@ 586 | clear 587 | stateless_arch_welcome 588 | help_edit_pacman_root 589 | terms_user_base_manager 590 | ;; 591 | # --use-now) 592 | # menu_select=$@ 593 | # clear 594 | # stateless_arch_welcome 595 | # help_use_now 596 | # terms_user_base_manager 597 | # ;; 598 | *) 599 | stateless_arch_welcome 600 | display_functions 601 | exit 0 602 | ;; 603 | esac 604 | -------------------------------------------------------------------------------- /usr/local/sbin/garbageauto: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ########################################## to use in systemd.timer 3 | function garbage_config(){ 4 | block_device_root=$(grub-probe / --target=device) 5 | declare parameter 6 | parameter[1]="branch-root" 7 | parameter[2]="branch-home" ### example sufix name to home subvol snapshots, case sensitive 8 | parameter[3]="branch-sysadmin-state" ### example sufix name to sysadmin subvol snapshots, case sensitive 9 | ##parameter[4]="sufix-name-branch" 10 | declare preserve ##### set preserve most recent branchs number, per parameter, into quotes 11 | preserve[1]="10" 12 | preserve[2]="12" # if equal 0, ALL subvols in parameter as deleted 13 | preserve[3]="7" 14 | ##parameter[4]="325" 15 | ## to preserve subvols common sufix, example clear old branch-root, but not old branch-root--pos. Case sensitive, insert new shield into quotes, after new pipe, example "pre|pos|created|int|before|after". comment to disable shield 16 | declare shield 17 | shield[1]="before|pos|created|int" # shield to parameter[1] 18 | shield[2]="another|parameter|here" # shield to parameter[2] 19 | shield[3]="Case|sensiTive" # shield to parameter[3] 20 | ##shield[4]="insert|shield|parameter|here" # DISABLED SHIELD 21 | branch_garbage 22 | } 23 | function branch_garbage(){ 24 | ##touch /var/log/garbagebranch.log create, if no existing, logfile to garbage 25 | toplevel_dir=$(mktemp -d -p /tmp) 26 | mount $block_device_root $toplevel_dir 27 | for operator in ${!parameter[@]} ; do 28 | moment=$(date +%Y-%m-%d--%H-%M-%S) 29 | if [ -z ${shield[$operator]} ] ; then 30 | subvol=($(btrfs su l -st $toplevel_dir | grep ${parameter[$operator]} | cut -d " " -f2 | grep -v $never_delete_id)) 31 | else 32 | subvol=($(btrfs su l -st $toplevel_dir | grep ${parameter[$operator]} | grep -Ev ${shield[$operator]} | cut -d " " -f2 | grep -v $never_delete_id)) 33 | fi 34 | totalcandidate=${#subvol[@]} 35 | controller=${preserve[$operator]} 36 | array_position=0 37 | echo "start clear old ${parameter[$operator]} in $moment" ### suggestion: redirect to logfile, example >> /var/log/garbagebranch.log 38 | while [ $totalcandidate -gt $controller ] ; do 39 | btrfs su del -i ${subvol[$array_position]} $toplevel_dir ## >> /var/log/garbagebranch.log 40 | btrfs filesystem sync $toplevel_dir 41 | let --totalcandidate 42 | let ++array_position 43 | done 44 | echo " end clear old ${parameter[$operator]} started in $moment" ### suggestion: redirect to logfile, example >> /var/log/garbagebranch.log 45 | done 46 | umount -R $toplevel_dir 47 | base-manager --bootloader-update-pos-garbage ### special entrypoint for garbage collectors in base-manager 48 | } 49 | never_delete=($(btrfs su show /)) 50 | never_delete_id=${never_delete[18]} 51 | garbage_config 52 | -------------------------------------------------------------------------------- /usr/local/sbin/pac-base: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | block_device_root=$(grub-probe / --target=device) 3 | default_root="@base_system" 4 | custom_grub_reinstall_routine="/bin/bash ./usr/local/sbin/user-customize-grub-setup" 5 | update_grub_command="grub-mkconfig -o /boot/grub/grub.cfg" 6 | transactional_dir=$(mktemp -d -p /tmp) 7 | toplevel_dir=$(mktemp -d -p /tmp) 8 | actual_root_array=($(btrfs su show /)) 9 | emergency_id=${actual_root_array[18]} 10 | function pre_mount_work(){ 11 | mount $block_device_root $toplevel_dir -o "subvolid="5 12 | } 13 | function transactional_operation(){ 14 | btrfs su snap $toplevel_dir/$default_root $toplevel_dir/@transactional_branch &&\ 15 | mount $block_device_root $transactional_dir -o "subvol="@transactional_branch &&\ 16 | btrfs filesystem sync $toplevel_dir 17 | } 18 | function bind_mount_pacman(){ 19 | mkdir -p /var/cache/pacman/pkg 20 | mount --bind /usr/local/ $transactional_dir/usr/local/ &&\ 21 | mount --bind /etc/pacman.d/ $transactional_dir/etc/pacman.d 22 | mount --bind /etc/pacman.conf $transactional_dir/etc/pacman.conf &&\ 23 | mount --bind /etc/mkinitcpio.conf $transactional_dir/etc/mkinitcpio.conf &&\ 24 | mount --bind /etc/mkinitcpio.d $transactional_dir/etc/mkinitcpio.d &&\ 25 | mount --bind /etc/modprobe.d $transactional_dir/etc/modprobe.d &&\ 26 | mount --bind /var/cache/pacman/pkg $transactional_dir/var/cache/pacman/pkg 27 | } 28 | function bind_mount_grub(){ 29 | mount --bind /usr/local/ $transactional_dir/usr/local/ &&\ 30 | mount --bind /etc/default/grub $transactional_dir/etc/default/grub &&\ 31 | mount --bind /etc/grub.d $transactional_dir/etc/grub.d &&\ 32 | mount --bind /etc/default/grub-btrfs/ $transactional_dir/etc/default/grub-btrfs/ 33 | } 34 | function manage_branch(){ 35 | manage_branch_1 36 | } 37 | function manage_branch_1(){ 38 | moment=$(date +%Y-%m-%d--%H-%M-%S) 39 | branch_name="@branch-root-pre-pacman--$moment" 40 | umount -Rv $transactional_dir &&\ 41 | mv $toplevel_dir/$default_root $toplevel_dir/$branch_name &&\ 42 | status="rootmoved" &&\ 43 | manage_branch_error || manage_branch_error 44 | } 45 | function manage_branch_2(){ 46 | status="none" 47 | btrfs filesystem sync $toplevel_dir &&\ 48 | mv $toplevel_dir/@transactional_branch $toplevel_dir/$default_root &&\ 49 | status="transactionalmoved" &&\ 50 | manage_branch_error || manage_branch_error 51 | } 52 | function manage_branch_3(){ 53 | status="none" &&\ 54 | btrfs filesystem sync $toplevel_dir &&\ 55 | mount $block_device_root $transactional_dir -o "subvol="$default_root && 56 | status="newrootmount" &&\ 57 | manage_branch_error || manage_branch_error 58 | } 59 | function manage_branch_error(){ 60 | if [ $status == "rootmoved" ] ; then 61 | manage_branch_2 62 | elif [ $status == "transactionalmoved" ] ; then 63 | manage_branch_3 64 | elif [ $status == "newrootmount" ] ; then 65 | status="newrootmount" 66 | elif [ $status == "error" ] || [ $status == "none" ] ; then 67 | echo "ocorreu um erro transacional crítico, movendo para o root atualmente em uso via base-manager --restore-root" && 68 | reason="pacman" id_to_restore=$emergency_id base-manager "--restore-root-pacman" && clear_dir 69 | else 70 | echo "ocorreu um erro transacional desconhecido. Abortando imediatamente. Confira manualmente o estado do sistema de arquivos e a lista de subvolumes. Se não houver nenhum chamado $default_root, o próximo boot falhará. O código de erro foi $err" && exit 1 71 | fi 72 | } 73 | function bootloader_update(){ 74 | bind_mount_grub && 75 | if [ -f /usr/local/sbin/grub-as-updated.log ] ; then 76 | transactional_dir=$transactional_dir arch-chroot $transactional_dir $custom_grub_reinstall_routine && 77 | rm /usr/local/sbin/grub-as-updated.log && 78 | arch-chroot $transactional_dir $update_grub_command 79 | else 80 | arch-chroot $transactional_dir $update_grub_command 81 | fi 82 | 83 | } 84 | function end_base_manager(){ 85 | if [ -d $toplevel_dir/$default_root ] ; then 86 | btrfs filesystem sync $toplevel_dir &&\ 87 | execute=$(btrfs property set -ts $toplevel_dir/$default_root ro true) &&\ 88 | btrfs filesystem sync $toplevel_dir &&\ 89 | clear_dir 90 | else 91 | status="error" && 92 | manage_branch_error 93 | fi 94 | } 95 | function clear_dir(){ 96 | umount -Rv $transactional_dir 97 | umount -Rv $toplevel_dir 98 | umount -Rv /tmp/tmp.* 99 | rmdir $transactional_dir 100 | rmdir $toplevel_dir 101 | } 102 | function update_grub(){ 103 | bootloader_update 104 | if [ $? -eq 0 ] ; then 105 | end_base_manager 106 | else 107 | echo "a atualização do bootloader na nova branch saiu com status de erro, revertendo transação" && update_grub_error 108 | fi 109 | } 110 | function update_grub_error(){ 111 | moment=$(date +%Y-%m-%d--%H-%M-%S) 112 | umount -Rv $transactional_dir &&\ 113 | mv $toplevel_dir/$default_root $toplevel_dir/@branch-deprecated-pos-pacman-grub-error--$moment &&\ 114 | mv $toplevel_dir/$branch_name $toplevel_dir/$default_root &&\ 115 | btrfs filesystem sync $toplevel_dir &&\ 116 | umount -Rv $toplevel_dir &&\ 117 | rmdir $transactional_dir &&\ 118 | rmdir $toplevel_dir &&\ 119 | echo "transação revertida para a branch válida mais recente devido a um erro anterior" || status="error" && manage_branch_error 120 | } 121 | 122 | function decision_pac(){ 123 | if [ $err -eq 0 ] ; then 124 | exit_pac_base_sucess 125 | else 126 | umount -Rv $transactional_dir &&\ 127 | btrfs su del $toplevel_dir/@transactional_branch &&\ 128 | umount -Rv $toplevel_dir &&\ 129 | rmdir $transactional_dir &&\ 130 | rmdir $toplevel_dir &&\ 131 | echo "transação abortada devido a um erro anterior" 132 | fi 133 | } 134 | function exit_pac_base_sucess(){ 135 | manage_branch && 136 | if [ $status == "newrootmount" ] ; then 137 | update_grub 138 | else 139 | status="error" && 140 | manage_branch_error 141 | fi 142 | } 143 | function run_pac_base (){ 144 | pre_mount_work 145 | transactional_operation 146 | bind_mount_pacman 147 | arch-chroot $transactional_dir pacman $command_pacman 148 | err=$? 149 | decision_pac 150 | } 151 | command_pacman=$@ 152 | run_pac_base 153 | -------------------------------------------------------------------------------- /usr/local/sbin/user-customize-grub-setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ###############################-set reinstall grub, mounts or another parameters############################## 3 | function grub_efi(){ 4 | mount $block_device_efi $efi_dir && 5 | grub-install --target='x86_64-efi' '--efi-directory='$efi_dir --recheck && exit 0 || exit 1 6 | } 7 | function grub_legacy(){ 8 | grub-install --target='i386-pc' $disk_for_grub --recheck && exit 0 || exit 1 9 | } 10 | ###############################---- complete and uncomment for your scenery 11 | #########---- for efi 12 | 13 | #$efi_dir="/boot/efi" 14 | #block_device_efi="/dev/sdX" 15 | #grub_efi 16 | 17 | ########---- for legacy 18 | 19 | #disk_for_grub="/dev/sdX" 20 | #grub_legacy 21 | --------------------------------------------------------------------------------