├── .gitlab-ci.yml ├── LICENSE.md ├── README.md └── vps2arch /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: debian:stable 2 | 3 | build: 4 | stage: build 5 | before_script: 6 | - apt-get update -y 7 | - DEBIAN_FRONTEND=noninteractive apt-get -o Acquire::Retires=10 install --no-install-recommends -qq libguestfs-tools busybox linux-image-amd64 gnupg1 openssh-client 8 | - ssh-keygen -q -N '' -f ~/.ssh/id_rsa 9 | script: 10 | - curl -fOL https://cdimage.debian.org/cdimage/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2 11 | - qemu-img create -f qcow2 -o preallocation=metadata newdisk.qcow2 4G 12 | - 'LIBGUESTFS_BACKEND=direct virt-resize --expand /dev/sda1 debian-12-nocloud-amd64.qcow2 newdisk.qcow2' 13 | - mv newdisk.qcow2 debian-12-nocloud-amd64.qcow2 14 | - 'LIBGUESTFS_BACKEND=direct virt-customize -a debian-12-nocloud-amd64.qcow2 --root-password password:root --ssh-inject root --install wget,ca-certificates,openssh-server --firstboot-command "dpkg-reconfigure -f noninteractive openssh-server"' 15 | after_script: 16 | - mv ~/.ssh/id_rsa id_rsa 17 | cache: 18 | paths: 19 | - debian-12-nocloud-amd64.qcow2 20 | - id_rsa 21 | policy: push 22 | 23 | .tests: 24 | retry: 1 25 | stage: test 26 | before_script: 27 | - apt-get update -y 28 | - DEBIAN_FRONTEND=noninteractive apt-get -o Acquire::Retires=10 install --no-install-recommends -qq qemu-system-x86 openssh-client sshpass 29 | - mkdir ~/.ssh 30 | - mv id_rsa ~/.ssh/id_rsa 31 | - printf '%s\n\t' 'Host *' 'ServerAliveInterval 15' 'UserKnownHostsFile /dev/null' 'StrictHostKeyChecking no' 'CheckHostIP no' > ~/.ssh/config 32 | - qemu-system-x86_64 -m 512 -daemonize -drive file=debian-12-nocloud-amd64.qcow2,if=virtio -net nic -net user,hostfwd=tcp::10022-:22 -display none -vga none -serial file:/tmp/serial 33 | - 'tail -f /tmp/serial &' 34 | - sleep 120 35 | - scp -P 10022 vps2arch root@127.0.0.1:vps2arch 36 | - ssh -p 10022 root@127.0.0.1 "chmod +x vps2arch" 37 | dependencies: 38 | - build 39 | cache: 40 | paths: 41 | - debian-12-nocloud-amd64.qcow2 42 | - id_rsa 43 | policy: pull 44 | 45 | .tests_uefi: 46 | retry: 1 47 | stage: test 48 | before_script: 49 | - apt-get update -y 50 | - DEBIAN_FRONTEND=noninteractive apt-get -o Acquire::Retires=10 install --no-install-recommends -qq qemu-system-x86 openssh-client ovmf sshpass 51 | - mkdir ~/.ssh 52 | - mv id_rsa ~/.ssh/id_rsa 53 | - printf '%s\n\t' 'Host *' 'ServerAliveInterval 15' 'UserKnownHostsFile /dev/null' 'StrictHostKeyChecking no' 'CheckHostIP no' > ~/.ssh/config 54 | - qemu-system-x86_64 -m 512 -daemonize -bios /usr/share/OVMF/OVMF_CODE.fd -drive file=debian-12-nocloud-amd64.qcow2,if=virtio -net nic -net user,hostfwd=tcp::10022-:22 -display none -vga none -serial file:/tmp/serial 55 | - 'tail -f /tmp/serial &' 56 | - sleep 120 57 | - scp -P 10022 vps2arch root@127.0.0.1:vps2arch 58 | - ssh -p 10022 root@127.0.0.1 "chmod +x vps2arch" 59 | dependencies: 60 | - build 61 | cache: 62 | paths: 63 | - debian-12-nocloud-amd64.qcow2 64 | - id_rsa 65 | policy: pull 66 | 67 | test_default: 68 | extends: .tests 69 | script: 70 | - 'ssh -p 10022 root@127.0.0.1 "./vps2arch && sync ; reboot -f" || true' 71 | - sleep 600 72 | - sshpass -proot ssh -p 10022 root@127.0.0.1 test -f /etc/arch-release 73 | 74 | test_netctl: 75 | extends: .tests 76 | script: 77 | - 'ssh -p 10022 root@127.0.0.1 "./vps2arch -n netctl && sync ; reboot -f" || true' 78 | - sleep 600 79 | - sshpass -proot ssh -p 10022 root@127.0.0.1 test -f /etc/arch-release 80 | 81 | test_syslinux: 82 | extends: .tests 83 | script: 84 | - 'ssh -p 10022 root@127.0.0.1 "./vps2arch -b syslinux && sync ; reboot -f" || true' 85 | - sleep 600 86 | - sshpass -proot ssh -p 10022 root@127.0.0.1 test -f /etc/arch-release 87 | 88 | test_default_uefi: 89 | extends: .tests_uefi 90 | script: 91 | - 'ssh -p 10022 root@127.0.0.1 "./vps2arch && sync ; reboot -f" || true' 92 | - sleep 600 93 | - sshpass -proot ssh -p 10022 root@127.0.0.1 test -f /etc/arch-release 94 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU General Public License 2 | ========================== 3 | 4 | _Version 2, June 1991_ 5 | _Copyright © 1989, 1991 Free Software Foundation, Inc.,_ 6 | _51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_ 7 | 8 | Everyone is permitted to copy and distribute verbatim copies 9 | of this license document, but changing it is not allowed. 10 | 11 | ### Preamble 12 | 13 | The licenses for most software are designed to take away your 14 | freedom to share and change it. By contrast, the GNU General Public 15 | License is intended to guarantee your freedom to share and change free 16 | software--to make sure the software is free for all its users. This 17 | General Public License applies to most of the Free Software 18 | Foundation's software and to any other program whose authors commit to 19 | using it. (Some other Free Software Foundation software is covered by 20 | the GNU Lesser General Public License instead.) You can apply it to 21 | your programs, too. 22 | 23 | When we speak of free software, we are referring to freedom, not 24 | price. Our General Public Licenses are designed to make sure that you 25 | have the freedom to distribute copies of free software (and charge for 26 | this service if you wish), that you receive source code or can get it 27 | if you want it, that you can change the software or use pieces of it 28 | in new free programs; and that you know you can do these things. 29 | 30 | To protect your rights, we need to make restrictions that forbid 31 | anyone to deny you these rights or to ask you to surrender the rights. 32 | These restrictions translate to certain responsibilities for you if you 33 | distribute copies of the software, or if you modify it. 34 | 35 | For example, if you distribute copies of such a program, whether 36 | gratis or for a fee, you must give the recipients all the rights that 37 | you have. You must make sure that they, too, receive or can get the 38 | source code. And you must show them these terms so they know their 39 | rights. 40 | 41 | We protect your rights with two steps: **(1)** copyright the software, and 42 | **(2)** offer you this license which gives you legal permission to copy, 43 | distribute and/or modify the software. 44 | 45 | Also, for each author's protection and ours, we want to make certain 46 | that everyone understands that there is no warranty for this free 47 | software. If the software is modified by someone else and passed on, we 48 | want its recipients to know that what they have is not the original, so 49 | that any problems introduced by others will not reflect on the original 50 | authors' reputations. 51 | 52 | Finally, any free program is threatened constantly by software 53 | patents. We wish to avoid the danger that redistributors of a free 54 | program will individually obtain patent licenses, in effect making the 55 | program proprietary. To prevent this, we have made it clear that any 56 | patent must be licensed for everyone's free use or not licensed at all. 57 | 58 | The precise terms and conditions for copying, distribution and 59 | modification follow. 60 | 61 | ### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 62 | 63 | **0.** This License applies to any program or other work which contains 64 | a notice placed by the copyright holder saying it may be distributed 65 | under the terms of this General Public License. The “Program”, below, 66 | refers to any such program or work, and a “work based on the Program” 67 | means either the Program or any derivative work under copyright law: 68 | that is to say, a work containing the Program or a portion of it, 69 | either verbatim or with modifications and/or translated into another 70 | language. (Hereinafter, translation is included without limitation in 71 | the term “modification”.) Each licensee is addressed as “you”. 72 | 73 | Activities other than copying, distribution and modification are not 74 | covered by this License; they are outside its scope. The act of 75 | running the Program is not restricted, and the output from the Program 76 | is covered only if its contents constitute a work based on the 77 | Program (independent of having been made by running the Program). 78 | Whether that is true depends on what the Program does. 79 | 80 | **1.** You may copy and distribute verbatim copies of the Program's 81 | source code as you receive it, in any medium, provided that you 82 | conspicuously and appropriately publish on each copy an appropriate 83 | copyright notice and disclaimer of warranty; keep intact all the 84 | notices that refer to this License and to the absence of any warranty; 85 | and give any other recipients of the Program a copy of this License 86 | along with the Program. 87 | 88 | You may charge a fee for the physical act of transferring a copy, and 89 | you may at your option offer warranty protection in exchange for a fee. 90 | 91 | **2.** You may modify your copy or copies of the Program or any portion 92 | of it, thus forming a work based on the Program, and copy and 93 | distribute such modifications or work under the terms of Section 1 94 | above, provided that you also meet all of these conditions: 95 | 96 | * **a)** You must cause the modified files to carry prominent notices 97 | stating that you changed the files and the date of any change. 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 | * **c)** If the modified program normally reads commands interactively 103 | when run, you must cause it, when started running for such 104 | interactive use in the most ordinary way, to print or display an 105 | announcement including an appropriate copyright notice and a 106 | notice that there is no warranty (or else, saying that you provide 107 | a warranty) and that users may redistribute the program under 108 | these conditions, and telling the user how to view a copy of this 109 | License. (Exception: if the Program itself is interactive but 110 | does not normally print such an announcement, your work based on 111 | the Program is not required to print an announcement.) 112 | 113 | These requirements apply to the modified work as a whole. If 114 | identifiable sections of that work are not derived from the Program, 115 | and can be reasonably considered independent and separate works in 116 | themselves, then this License, and its terms, do not apply to those 117 | sections when you distribute them as separate works. But when you 118 | distribute the same sections as part of a whole which is a work based 119 | on the Program, the distribution of the whole must be on the terms of 120 | this License, whose permissions for other licensees extend to the 121 | entire whole, and thus to each and every part regardless of who wrote it. 122 | 123 | Thus, it is not the intent of this section to claim rights or contest 124 | your rights to work written entirely by you; rather, the intent is to 125 | exercise the right to control the distribution of derivative or 126 | collective works based on the Program. 127 | 128 | In addition, mere aggregation of another work not based on the Program 129 | with the Program (or with a work based on the Program) on a volume of 130 | a storage or distribution medium does not bring the other work under 131 | the scope of this License. 132 | 133 | **3.** You may copy and distribute the Program (or a work based on it, 134 | under Section 2) in object code or executable form under the terms of 135 | Sections 1 and 2 above provided that you also do one of the following: 136 | 137 | * **a)** Accompany it with the complete corresponding machine-readable 138 | source code, which must be distributed under the terms of Sections 139 | 1 and 2 above on a medium customarily used for software interchange; or, 140 | * **b)** Accompany it with a written offer, valid for at least three 141 | years, to give any third party, for a charge no more than your 142 | cost of physically performing source distribution, a complete 143 | machine-readable copy of the corresponding source code, to be 144 | distributed under the terms of Sections 1 and 2 above on a medium 145 | customarily used for software interchange; or, 146 | * **c)** Accompany it with the information you received as to the offer 147 | to distribute corresponding source code. (This alternative is 148 | allowed only for noncommercial distribution and only if you 149 | received the program in object code or executable form with such 150 | an offer, in accord with Subsection b above.) 151 | 152 | The source code for a work means the preferred form of the work for 153 | making modifications to it. For an executable work, complete source 154 | code means all the source code for all modules it contains, plus any 155 | associated interface definition files, plus the scripts used to 156 | control compilation and installation of the executable. However, as a 157 | special exception, the source code distributed need not include 158 | anything that is normally distributed (in either source or binary 159 | form) with the major components (compiler, kernel, and so on) of the 160 | operating system on which the executable runs, unless that component 161 | itself accompanies the executable. 162 | 163 | If distribution of executable or object code is made by offering 164 | access to copy from a designated place, then offering equivalent 165 | access to copy the source code from the same place counts as 166 | distribution of the source code, even though third parties are not 167 | compelled to copy the source along with the object code. 168 | 169 | **4.** You may not copy, modify, sublicense, or distribute the Program 170 | except as expressly provided under this License. Any attempt 171 | otherwise to copy, modify, sublicense or distribute the Program is 172 | void, and will automatically terminate your rights under this License. 173 | However, parties who have received copies, or rights, from you under 174 | this License will not have their licenses terminated so long as such 175 | parties remain in full compliance. 176 | 177 | **5.** You are not required to accept this License, since you have not 178 | signed it. However, nothing else grants you permission to modify or 179 | distribute the Program or its derivative works. These actions are 180 | prohibited by law if you do not accept this License. Therefore, by 181 | modifying or distributing the Program (or any work based on the 182 | Program), you indicate your acceptance of this License to do so, and 183 | all its terms and conditions for copying, distributing or modifying 184 | the Program or works based on it. 185 | 186 | **6.** Each time you redistribute the Program (or any work based on the 187 | Program), the recipient automatically receives a license from the 188 | original licensor to copy, distribute or modify the Program subject to 189 | these terms and conditions. You may not impose any further 190 | restrictions on the recipients' exercise of the rights granted herein. 191 | You are not responsible for enforcing compliance by third parties to 192 | this License. 193 | 194 | **7.** If, as a consequence of a court judgment or allegation of patent 195 | infringement or for any other reason (not limited to patent issues), 196 | conditions are imposed on you (whether by court order, agreement or 197 | otherwise) that contradict the conditions of this License, they do not 198 | excuse you from the conditions of this License. If you cannot 199 | distribute so as to satisfy simultaneously your obligations under this 200 | License and any other pertinent obligations, then as a consequence you 201 | may not distribute the Program at all. For example, if a patent 202 | license would not permit royalty-free redistribution of the Program by 203 | all those who receive copies directly or indirectly through you, then 204 | the only way you could satisfy both it and this License would be to 205 | refrain entirely from distribution of the Program. 206 | 207 | If any portion of this section is held invalid or unenforceable under 208 | any particular circumstance, the balance of the section is intended to 209 | apply and the section as a whole is intended to apply in other 210 | circumstances. 211 | 212 | It is not the purpose of this section to induce you to infringe any 213 | patents or other property right claims or to contest validity of any 214 | such claims; this section has the sole purpose of protecting the 215 | integrity of the free software distribution system, which is 216 | implemented by public license practices. Many people have made 217 | generous contributions to the wide range of software distributed 218 | through that system in reliance on consistent application of that 219 | system; it is up to the author/donor to decide if he or she is willing 220 | to distribute software through any other system and a licensee cannot 221 | impose that choice. 222 | 223 | This section is intended to make thoroughly clear what is believed to 224 | be a consequence of the rest of this License. 225 | 226 | **8.** If the distribution and/or use of the Program is restricted in 227 | certain countries either by patents or by copyrighted interfaces, the 228 | original copyright holder who places the Program under this License 229 | may add an explicit geographical distribution limitation excluding 230 | those countries, so that distribution is permitted only in or among 231 | countries not thus excluded. In such case, this License incorporates 232 | the limitation as if written in the body of this License. 233 | 234 | **9.** The Free Software Foundation may publish revised and/or new versions 235 | of the General Public License from time to time. Such new versions will 236 | be similar in spirit to the present version, but may differ in detail to 237 | address new problems or concerns. 238 | 239 | Each version is given a distinguishing version number. If the Program 240 | specifies a version number of this License which applies to it and “any 241 | later version”, you have the option of following the terms and conditions 242 | either of that version or of any later version published by the Free 243 | Software Foundation. If the Program does not specify a version number of 244 | this License, you may choose any version ever published by the Free Software 245 | Foundation. 246 | 247 | **10.** If you wish to incorporate parts of the Program into other free 248 | programs whose distribution conditions are different, write to the author 249 | to ask for permission. For software which is copyrighted by the Free 250 | Software Foundation, write to the Free Software Foundation; we sometimes 251 | make exceptions for this. Our decision will be guided by the two goals 252 | of preserving the free status of all derivatives of our free software and 253 | of promoting the sharing and reuse of software generally. 254 | 255 | ### NO WARRANTY 256 | 257 | **11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 258 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 259 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 260 | PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 261 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 262 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 263 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 264 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 265 | REPAIR OR CORRECTION. 266 | 267 | **12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 268 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 269 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 270 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 271 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 272 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 273 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 274 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 275 | POSSIBILITY OF SUCH DAMAGES. 276 | 277 | END OF TERMS AND CONDITIONS 278 | 279 | ### How to Apply These Terms to Your New Programs 280 | 281 | If you develop a new program, and you want it to be of the greatest 282 | possible use to the public, the best way to achieve this is to make it 283 | free software which everyone can redistribute and change under these terms. 284 | 285 | To do so, attach the following notices to the program. It is safest 286 | to attach them to the start of each source file to most effectively 287 | convey the exclusion of warranty; and each file should have at least 288 | the “copyright” line and a pointer to where the full notice is found. 289 | 290 | 291 | Copyright (C) 292 | 293 | This program is free software; you can redistribute it and/or modify 294 | it under the terms of the GNU General Public License as published by 295 | the Free Software Foundation; either version 2 of the License, or 296 | (at your option) any later version. 297 | 298 | This program is distributed in the hope that it will be useful, 299 | but WITHOUT ANY WARRANTY; without even the implied warranty of 300 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 301 | GNU General Public License for more details. 302 | 303 | You should have received a copy of the GNU General Public License along 304 | with this program; if not, write to the Free Software Foundation, Inc., 305 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 306 | 307 | Also add information on how to contact you by electronic and paper mail. 308 | 309 | If the program is interactive, make it output a short notice like this 310 | when it starts in an interactive mode: 311 | 312 | Gnomovision version 69, Copyright (C) year name of author 313 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 314 | This is free software, and you are welcome to redistribute it 315 | under certain conditions; type `show c' for details. 316 | 317 | The hypothetical commands `show w` and `show c` should show the appropriate 318 | parts of the General Public License. Of course, the commands you use may 319 | be called something other than `show w' and `show c`; they could even be 320 | mouse-clicks or menu items--whatever suits your program. 321 | 322 | You should also get your employer (if you work as a programmer) or your 323 | school, if any, to sign a “copyright disclaimer” for the program, if 324 | necessary. Here is a sample; alter the names: 325 | 326 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 327 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 328 | 329 | , 1 April 1989 330 | Ty Coon, President of Vice 331 | 332 | This General Public License does not permit incorporating your program into 333 | proprietary programs. If your program is a subroutine library, you may 334 | consider it more useful to permit linking proprietary applications with the 335 | library. If this is what you want to do, use the GNU Lesser General 336 | Public License instead of this License. 337 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | VPS2Arch 2 | ======== 3 | 4 | The fastest way to convert a _VPS_ to [Arch Linux](https://www.archlinux.org/)! 5 | 6 | Author 7 | ------ 8 | 9 | [Timothy Redaelli](mailto:timothy@fsfe.org) 10 | 11 | Description 12 | ----------- 13 | 14 | This script is used to convert a _VPS_, running another linux distro, to _Arch Linux_. 15 | It should be **only** used if your _VPS_ provider doesn't provide you an _Arch Linux_ image. 16 | 17 | Disclaimer 18 | ---------- 19 | 20 | > I'm not responsible for any damage in your system and/or any violation of the agreement between you and your vps provider. 21 | > **Use at your own risk!** 22 | 23 | How To 24 | ------ 25 | 26 | Download the script on your _VPS_ and execute it with root privileges 27 | 28 | **WARNING** The script will **delete** any data in your _VPS_! 29 | 30 | wget http://tinyurl.com/vps2arch 31 | chmod +x vps2arch 32 | ./vps2arch 33 | 34 | Some _Debian_ _VPS_ images don't have the _CA certificates_ installed, so `wget` will give you the following errors: 35 | 36 | ERROR: The certificate of `gitlab.com' is not trusted. 37 | ERROR: The certificate of `gitlab.com' hasn't got a known issuer. 38 | 39 | To fix them just execute `apt-get install ca-certificates` and then re-execute the previous commands. 40 | 41 | How does it work? 42 | ----------------- 43 | 44 | It's Black Magic. 45 | Just kiddin' 😏, the script itself is very simple. 46 | 47 | In a nutshell, it will download the _Arch Linux Bootstrap Image_ and (see the [wiki](https://wiki.archlinux.org/index.php/Install_from_existing_Linux#Method_B:_Using_the_Bootstrap_Image_.28recommended.29)), 48 | extract the image to / and configure the _Bootstrap chroot_. 49 | 50 | Now, about the **critical** part: 51 | 52 | > How can you wipe the system without breaking everything? 53 | 54 | It's simple: using `ld.so` from the _Bootstrap chroot_ to launch the `chroot` tool. 55 | 56 | Since it will erase all the system directories except from the _Bootstrap chroot_, `/dev`, `/proc`, `/sys` and the like, 57 | the only way to launch a command inside the _Bootstrap chroot_ is to using ld.so from the _Bootstrap chroot_ itself. 58 | 59 | At this point _Arch Linux_ has been installed, but not configured. 60 | The script will provide a SSH-able system automagically configuring grub (or syslinux), network and restoring the root password from the original system (or by using `vps2arch` as password if no root password was set). 61 | 62 | Once done doing its job, the script will ask you to manually reboot your _VPS_ and voilà, PROFIT! 63 | 64 | Does it really work? 65 | -------------------- 66 | 67 | Yes, it does! 68 | 69 | On the [Tested VPS Providers](https://gitlab.com/drizzt/vps2arch/wikis/Tested-VPS-Providers) wiki page you can find a list of **Tested VPS Providers**. 70 | 71 | Theoretically it should also work on **real** computers (running linux), but I think it's not worth it, 72 | because you can install it in the canonical way. 73 | 74 | Contributing 75 | ------------ 76 | 77 | If you have any useful modification, please use **Pull requests**. 78 | If you have successfully used this script on a different _distro_ - _VPS_ combination, please contact me so that I can update the above list. 79 | 80 | If you are not a developer, but you still want to contribute, you can donate me an account on your _VPS_ provider and I'll do my best to support it. 81 | Or you can just donate me some bucks I'll spend to buy a _VPS_ on your provider in order to support it. 82 | 83 | Caveats 84 | ------- 85 | 86 | _IPv6_ currently is not supported. If you need to use it, please configure it manually. 87 | -------------------------------------------------------------------------------- /vps2arch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2015, Timothy Redaelli 4 | 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License at for 14 | # more details. 15 | 16 | set -e 17 | 18 | # Gathering informations about actual environment. 19 | if command -v wget >/dev/null 2>&1; then 20 | _download() { wget -O- "$@" ; } 21 | elif command -v curl >/dev/null 2>&1; then 22 | _download() { curl -fL "$@" ; } 23 | else 24 | echo "This script needs curl or wget" >&2 25 | exit 2 26 | fi 27 | 28 | if ! command -v zstd >/dev/null 2>&1; then 29 | _download "https://people.redhat.com/~tredaell/zstd" > /usr/bin/zstd 30 | chmod +x /usr/bin/zstd 31 | fi 32 | 33 | get_worldwide_mirrors() { 34 | _download 'https://www.archlinux.org/mirrorlist/?country=all&protocol=https&ip_version=4' | awk '/^## /{if ($2 == "Worldwide") { flag=1 } else { flag=0 } } /^#Server/ { if (flag) { sub(/\/\$repo.*/, ""); print $3 } }' 35 | } 36 | 37 | cpu_type=$(uname -m) 38 | 39 | is_openvz() { [ -d /proc/vz ] && [ ! -d /proc/bc ]; } 40 | is_lxc() { grep -aqw container=lxc /proc/1/environ ; } 41 | 42 | download() { 43 | _download_path="$1" _download_x= 44 | shift 45 | for _download_x in $mirrors; do 46 | _download "$_download_x/$_download_path" && return 0 47 | done 48 | return 1 49 | } 50 | 51 | download_and_extract_bootstrap() { 52 | download iso/latest/sha256sums.txt | grep -F "$cpu_type.tar.zst" > "sha256sums.txt" 53 | read -r _ _download_and_extract_bootstrap_filename < "sha256sums.txt" 54 | download "iso/latest/$_download_and_extract_bootstrap_filename" > "$_download_and_extract_bootstrap_filename" 55 | grep -v archlinux-bootstrap-x86_64.tar.zst sha256sums.txt | sha256sum -c || exit 1 56 | zstd -d -c "$_download_and_extract_bootstrap_filename" | tar -xpf - 57 | rm -f "$_download_and_extract_bootstrap_filename" 58 | cp -L /etc/resolv.conf "/root.$cpu_type/etc" 59 | 60 | # Mount options taked from arch-chroot script 61 | mount -t proc proc -o nosuid,noexec,nodev "/root.$cpu_type/proc" 62 | mount -t sysfs sys -o nosuid,noexec,nodev,ro "/root.$cpu_type/sys" 63 | mount -t devtmpfs -o mode=0755,nosuid udev "/root.$cpu_type/dev" 64 | mkdir -p "/root.$cpu_type/dev/pts" "/root.$cpu_type/dev/shm" 65 | mount -t devpts -o mode=0620,gid=5,nosuid,noexec devpts "/root.$cpu_type/dev/pts" 66 | mount -t tmpfs -o mode=1777,nosuid,nodev shm "/root.$cpu_type/dev/shm" 67 | mount -t tmpfs -o nosuid,nodev,mode=0755 run "/root.$cpu_type/run" 68 | mount -t tmpfs -o mode=1777,strictatime,nodev,nosuid tmp "/root.$cpu_type/tmp" 69 | # FIXME support multiple partitions 70 | mount --bind / "/root.$cpu_type/mnt" 71 | findmnt /boot >/dev/null && mount --bind /boot "/root.$cpu_type/mnt/boot" 72 | findmnt /boot/efi >/dev/null && mount --bind /boot/efi "/root.$cpu_type/mnt/boot/efi" 73 | # Workaround for Debian 74 | mkdir -p "/root.$cpu_type/run/shm" 75 | # Workaround for OpenVZ 76 | rm -f "/root.$cpu_type/etc/mtab" 77 | cp -L /etc/mtab "/root.$cpu_type/etc/mtab" 78 | } 79 | 80 | chroot_exec() { 81 | chroot "/root.$cpu_type" /bin/bash -c "$*" 82 | } 83 | 84 | configure_chroot() { 85 | for _configure_chroot_m in $mirrors; do 86 | echo "Server = $_configure_chroot_m/\$repo/os/\$arch" 87 | done >> "/root.$cpu_type/etc/pacman.d/mirrorlist" 88 | # Install and initialize haveged if needed 89 | if ! is_openvz && ! pidof haveged >/dev/null; then 90 | # Disable signature check, install and launch haveged and re-enable signature checks. 91 | sed -i.bak "s/^[[:space:]]*SigLevel[[:space:]]*=.*$/SigLevel = Never/" "/root.$cpu_type/etc/pacman.conf" 92 | chroot_exec 'pacman --needed --noconfirm -Sy haveged && haveged' 93 | mv "/root.$cpu_type/etc/pacman.conf.bak" "/root.$cpu_type/etc/pacman.conf" 94 | fi 95 | chroot_exec 'pacman-key --init && pacman-key --populate archlinux' 96 | # Update the archlinux-keyring in bootstrap 97 | chroot_exec 'pacman --needed --noconfirm -Sy archlinux-keyring' 98 | # Generate fstab 99 | chroot_exec 'genfstab /mnt >> /etc/fstab' 100 | } 101 | 102 | save_root_pass() { 103 | grep '^root:' /etc/shadow > "/root.$cpu_type/root.passwd" 104 | chmod 0600 "/root.$cpu_type/root.passwd" 105 | } 106 | 107 | backup_old_files() { 108 | cp -fL /etc/hostname /etc/localtime "/root.$cpu_type/etc/" || true 109 | } 110 | 111 | delete_all() { 112 | # Remove immutable flag from any files / directories 113 | if command -v chattr >/dev/null 2>&1; then 114 | find / -type f \( ! -path '/dev/*' -and ! -path '/proc/*' -and ! -path '/sys/*' -and ! -path '/selinux/*' -and ! -path "/root.$cpu_type/*" \) \ 115 | -exec chattr -i {} + 2>/dev/null || true 116 | fi 117 | # Delete *all* files from / 118 | find / \( ! -path '/dev/*' -and ! -path '/proc/*' -and ! -path '/sys/*' -and ! -path '/selinux/*' -and ! -path "/root.$cpu_type/*" \) -delete 2>/dev/null || true 119 | } 120 | 121 | install_packages() { 122 | set -- "/root.$cpu_type/usr/lib"/ld-*.so.2 123 | ld_so=$1 124 | 125 | set -- base openssh reflector 126 | is_openvz || set -- "$@" linux lvm2 127 | [ "$bootloader" != "none" ] && set -- "$@" "$bootloader" 128 | # XXX Install gptdisk for syslinux. To be removed then FS#45029 will be closed 129 | [ "$bootloader" = "syslinux" ] && set -- "$@" gptfdisk 130 | [ -f /sys/firmware/efi/fw_platform_size ] && set -- "$@" efibootmgr 131 | [ "$network" = "netctl" ] && set -- "$@" netctl 132 | while read -r _ mountpoint filesystem _; do 133 | [ "$mountpoint" = "/" ] && [ "$filesystem" = "xfs" ] && packages="$packages xfsprogs" 134 | done < /proc/mounts 135 | # Black magic! 136 | "$ld_so" --library-path "/root.$cpu_type/usr/lib" \ 137 | "/root.$cpu_type/usr/bin/chroot" "/root.$cpu_type" /usr/bin/pacstrap -M /mnt "$@" 138 | cp -L "/root.$cpu_type/etc/resolv.conf" /etc 139 | } 140 | 141 | restore_root_pass() { 142 | # If the root password is not set, use vps2arch 143 | if grep -qE '^root:[^$]' "/root.$cpu_type/root.passwd"; then 144 | echo "root:vps2arch" | chpasswd 145 | else 146 | sed -i '/^root:/d' /etc/shadow 147 | cat "/root.$cpu_type/root.passwd" >> /etc/shadow 148 | fi 149 | } 150 | 151 | cleanup() { 152 | mv "/root.$cpu_type/etc/fstab" "/etc/fstab" 153 | awk "/\/root.$cpu_type/ {print \$2}" /proc/mounts | sort -r | xargs umount -nl || true 154 | rm -rf "/root.$cpu_type/" 155 | } 156 | 157 | configure_bootloader() { 158 | _configure_bootloader_root_devs='' 159 | _configure_bootloader_tmp='' 160 | _configure_bootloader_needs_lvm2=0 161 | _configure_bootloader_uefi=0 162 | _configure_bootloader_root_dev=$(findmnt -no SOURCE /) 163 | 164 | case $_configure_bootloader_root_dev in 165 | /dev/mapper/*) _configure_bootloader_needs_lvm2=1 ;; 166 | esac 167 | if [ -f /sys/firmware/efi/fw_platform_size ]; then 168 | _configure_bootloader_uefi=$(cat /sys/firmware/efi/fw_platform_size) 169 | fi 170 | 171 | if [ $_configure_bootloader_needs_lvm2 -eq 1 ]; then 172 | # Some distro doesn't use lvmetad by default 173 | sed -i.bak 's/use_lvmetad = 1/use_lvmetad = 0/g' /etc/lvm/lvm.conf 174 | fi 175 | 176 | if [ "$bootloader" = "grub" ]; then 177 | # If you are still using eth* as interface name, disable "strange" ifnames 178 | grep -q '^[[:space:]]*eth' /proc/net/dev && \ 179 | sed -i.bak 's/GRUB_CMDLINE_LINUX_DEFAULT="/&net.ifnames=0 /' /etc/default/grub 180 | 181 | # Disable "graphic" terminal output 182 | sed -i.bak 's/^#GRUB_TERMINAL_OUTPUT=console/GRUB_TERMINAL_OUTPUT=console/' /etc/default/grub 183 | 184 | if [ $_configure_bootloader_needs_lvm2 -eq 1 ]; then 185 | _configure_bootloader_vg=$(lvs --noheadings "$_configure_bootloader_root_dev" | awk '{print $2}') 186 | _configure_bootloader_root_dev=$(pvs --noheadings | awk -v vg="$_configure_bootloader_vg" '($2 == vg) { print $1 }') 187 | fi 188 | for _configure_bootloader_root_dev in $_configure_bootloader_root_dev; do 189 | _configure_bootloader_tmp=$(lsblk -npsro TYPE,NAME "$_configure_bootloader_root_dev" | awk '($1 == "disk") { print $2}') 190 | case " $_configure_bootloader_root_devs " in 191 | *" $_configure_bootloader_tmp "*) ;; 192 | *) _configure_bootloader_root_devs="${_configure_bootloader_root_devs:+$_configure_bootloader_root_devs }$_configure_bootloader_tmp" ;; 193 | esac 194 | done 195 | case $_configure_bootloader_uefi in 196 | 0) 197 | for _configure_bootloader_root_dev in $_configure_bootloader_root_devs; do 198 | grub-install --target=i386-pc --recheck --force "$_configure_bootloader_root_dev" 199 | done 200 | ;; 201 | 64) 202 | grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB 203 | ;; 204 | esac 205 | grub-mkconfig > /boot/grub/grub.cfg 206 | elif [ "$bootloader" = "syslinux" ]; then 207 | # If you are still using eth* as interface name, disable "strange" ifnames 208 | grep -q '^[[:space:]]*eth' /proc/net/dev && tmp="net.ifnames=0" 209 | syslinux-install_update -ami 210 | sed -i "s;\(^[[:space:]]*APPEND.*\)root=[^[:space:]]*;\1root=$_configure_bootloader_root_dev${_configure_bootloader_tmp:+ $_configure_bootloader_tmp};" /boot/syslinux/syslinux.cfg 211 | fi 212 | 213 | if [ $_configure_bootloader_needs_lvm2 -eq 1 ]; then 214 | mv /etc/lvm/lvm.conf.bak /etc/lvm/lvm.conf 215 | sed -i '/HOOKS/s/block/& lvm2/' /etc/mkinitcpio.conf 216 | mkinitcpio -p linux 217 | fi 218 | } 219 | 220 | configure_network() { 221 | read -r _configure_network_dev _configure_network_gateway <<-EOF 222 | $(awk '$2 == "00000000" { ip = strtonum(sprintf("0x%s", $3)); 223 | printf ("%s\t%d.%d.%d.%d", $1, 224 | rshift(and(ip,0x000000ff),00), rshift(and(ip,0x0000ff00),08), 225 | rshift(and(ip,0x00ff0000),16), rshift(and(ip,0xff000000),24)) ; exit }' < /proc/net/route) 226 | EOF 227 | 228 | set -- "$(ip addr show dev "$_configure_network_dev" | awk '($1 == "inet") { print $2 }')" 229 | _configure_network_ip=$* 230 | 231 | # FIXME Not supported for "P2P" interfaces, such as venet, yet 232 | if [ "$network" = "systemd-networkd" ]; then 233 | cat > /etc/systemd/network/default.network <<-EOF 234 | [Match] 235 | Name=$_configure_network_dev 236 | 237 | [Network] 238 | Gateway=$_configure_network_gateway 239 | EOF 240 | for _configure_network_ip in $_configure_network_ip; do 241 | echo "Address=$_configure_network_ip" 242 | done >> /etc/systemd/network/default.network 243 | systemctl enable systemd-networkd 244 | elif [ "$network" = "netctl" ]; then 245 | cat > /etc/netctl/default <<-EOF 246 | Interface=$_configure_network_dev 247 | Connection=ethernet 248 | IP=static 249 | Address=($_configure_network_ip) 250 | EOF 251 | if [ "$_configure_network_gateway" = "0.0.0.0" ]; then 252 | echo 'Routes=(0.0.0.0/0)' 253 | else 254 | echo "Gateway=$_configure_network_gateway" 255 | fi >> /etc/netctl/default 256 | netctl enable default 257 | fi 258 | 259 | systemctl enable sshd 260 | } 261 | 262 | finalize() { 263 | # OpenVZ hacks 264 | if is_openvz; then 265 | # Virtuozzo 7 works with systemd, but it needs /etc/resolvconf/resolv.conf.d directory 266 | mkdir -p /etc/resolvconf/resolv.conf.d 267 | fi 268 | 269 | # Enable SSH login for user root (#3) 270 | sed -i '/^#PermitRootLogin\s/s/.*/&\nPermitRootLogin yes/' /etc/ssh/sshd_config 271 | 272 | # Run reflector to get updated mirrors 273 | 274 | cat <<-EOF 275 | 276 | Reflector: Rating the 35 most recently synced HTTPS servers, sorting them by download speed 277 | 278 | EOF 279 | 280 | reflector -l 35 -p https --sort rate --save /etc/pacman.d/mirrorlist 281 | 282 | cat <<-EOF 283 | Hi, 284 | your VM has successfully been reimaged with Arch Linux. 285 | 286 | This script configured $bootloader as bootloader and $network for networking. 287 | 288 | When you are finished with your post-installation, you'll need to reboot the VM the rough way: 289 | # sync ; reboot -f 290 | 291 | Then you'll be able to connect to your VM using SSH and to login using your old root password (or "vps2arch" if you didn't have a root password). 292 | EOF 293 | } 294 | 295 | bootloader=grub 296 | network=systemd-networkd 297 | mirrors= 298 | 299 | while getopts ":b:m:n:h" opt; do 300 | case $opt in 301 | b) 302 | if [ "$OPTARG" != "grub" ] && [ "$OPTARG" != "syslinux" ] && [ "$OPTARG" != "none" ]; then 303 | echo "Invalid bootloader specified" >&2 304 | exit 1 305 | fi 306 | bootloader="$OPTARG" 307 | ;; 308 | m) 309 | mirrors="${mirrors:+$mirrors }$OPTARG" 310 | ;; 311 | n) 312 | if [ "$OPTARG" != "systemd-networkd" ] && [ "$OPTARG" != "netctl" ] && [ "$OPTARG" != "none" ]; then 313 | echo "Invalid networking configuration system specified" >&2 314 | exit 1 315 | fi 316 | network="$OPTARG" 317 | ;; 318 | h) 319 | cat <<-EOF 320 | usage: ${0##*/} [options] 321 | 322 | Options: 323 | -b (grub|syslinux) Use the specified bootloader. When this option is omitted, it defaults to grub. 324 | -n (systemd-networkd|netctl) Use the specified networking configuration system. When this option is omitted, it defaults to systemd-networkd. 325 | -m mirror Use the provided mirror (you can specify this option more than once). 326 | 327 | -h Print this help message 328 | 329 | Warning: 330 | On OpenVZ containers the bootloader will be not installed and the networking configuration system will be enforced to netctl. 331 | EOF 332 | exit 0 333 | ;; 334 | :) 335 | printf "%s: option requires an argument -- '%s'\n" "${0##*/}" "$OPTARG" >&2 336 | exit 1 337 | ;; 338 | ?) 339 | printf "%s: invalid option -- '%s'\n" "${0##*/}" "$OPTARG" >&2 340 | exit 1 341 | ;; 342 | esac 343 | done 344 | shift $((OPTIND - 1)) 345 | 346 | [ -z "$mirrors" ] && mirrors=$(get_worldwide_mirrors) 347 | 348 | 349 | if is_openvz; then 350 | bootloader=none 351 | network=netctl 352 | elif is_lxc; then 353 | bootloader=none 354 | fi 355 | 356 | cd / 357 | download_and_extract_bootstrap 358 | configure_chroot 359 | save_root_pass 360 | backup_old_files 361 | delete_all 362 | install_packages 363 | restore_root_pass 364 | cleanup 365 | configure_bootloader 366 | configure_network 367 | finalize 368 | --------------------------------------------------------------------------------