# Project management tools > Tools for deployments and project management ## What this does [Uberspace](https://uberspace.de) has a great routing setup for Apache sites: You place a directory or symbolic link with the name of the domain (like `www.example.com`) in `/var/www/virtual//` and every request to this domain is routed to the directory. As a user with a [pretty complex routing setup](https://git.lukasbestle.com/groups/sites), I wanted to automate setting up new sites and updating them automatically from a Git repository. This toolset provides some CLI tools to make that possible. ### Example Let's say you have a main site at `example.com` and another project at `subdomain.example.com`. You want the main site to be accessible from `example.net` as well. The main site is located at a GitHub repository from where everything should be deployed automatically. The result is the following setup: example.com/example.net -> Main site ("main_site") subdomain.example.com -> Other project ("other_project") This is a tutorial on how you would implement this setup with this toolset. 1. **Make sure you follow the setup instructions below.** 2. **Create the sites** ```bash # Create a new site and set the origin URL to the clone URL of your GitHub repository. site_add main_site https://github.com/organization/main.git # "other_project" is a local project and does not have an origin. site_add other_project ``` You can now locate the sites at `~/web/sites/main_site` and `~/web/sites/other_project`. Using `project_add` is similar, but it uses a custom project path – the headers of the files in `bin/` contain detailed usage information. 3. **Get the current state from your GitHub repository (other Git repositories work the same)** As "main_site" was setup using a clone URL, you can use `site_deploy ` to get and install the current state of your project: ```bash # You need the full SHA-1 hash of your commit for this to work. # Automatic deployments using web hooks do this for you automatically. site_deploy main_site 78ca1d2fa93147b0... ``` There is now a log of the deployment in `~/web/sites/main_site/logs/`, the project code at `~/web/sites/main_site/versions/00001-78ca1d2fa93147b0...` and a symlink to the code at `~/web/sites/main_site/current`. This symlink is automatically created if a deployment succeeded. 4. **Set the domains to make your project accessible** Now that your projects are installed and ready, you can let this toolset create links, so the (abstract) sites are made available at specific domains: ```bash # "main_site" should be available at example.com and example.net site_link main_site example.com site_link main_site example.net # "other_project" should be available at subdomain.example.com site_link other_project subdomain.example.com ``` When deleting a site with `site_remove`, all of these domain links are automatically removed as well. You can also use `site_unlink` to unlink specific domains. If you setup automatic deployments (see below), your sites are automatically updated to the newest revision. This is done by cloning or fetching the repository using `project_deploy` and updating the links, so the domain link always points to the latest revision. Let's say you committed a mistake (haha) and you want to rollback to the last deployed (working) revision. Since our example site "main_site" is deployable (it has an origin repository), it stores a history of (by default) 5 versions and keeps the link to the last version. This means that you can easily return to the last version and manually to an even older version: ```bash # Rollback to the last version site_rollback main_site # Manually rollback to an even older version cd ~/web/sites/main_site rm last mv current last ln -s versions/ current ``` ## Features - Create and delete projects (general repositories like CLI tools) and sites (projects for the webserver) - Set an origin Git repository and branch to get new versions from - Create and delete links from one or multiple domains to a site - Automatic Deployments from GitHub, GitLab or any other Git remote - Run an optional setup script (`.postdeploy.sh` in the repository root) in each deployment's destination directory - Reverse a deployable project to the last version in one step ### Directory structure of a project Every project/site follows this directory structure: .branch # Branch to allow deployments for (see "Deployment setup") .domains # Site-specific: List of linked domains for this site .origin # URL of the origin repository .project # Empty file determining that this is a project current # Symlink to the currently active version in versions/ ├── data # Never directly accessible by user agents and never overwritten ├── last # Symlink to the last active version in versions/ ├── logs # Logs of all deployments ├── .log ├── .log repo # Clone of the project's Git repository ├── … versions # Copies of the repository checked out to a specific revision ├── - │ └── └── - └── ### Usage without any kind of deployment If you don't want to keep old versions of your code and use automatic deployment, simply leave out the `` parameter and you end up with a structure like this: .domains # Site-specific: List of linked domains for this site .project # Empty file determining that this is a project current # Directory for your project files ├── data # Never directly accessible by user agents and never overwritten └── This is useful for projects that aren't using version control. You can still use domain linking with these though. ### Deployment setup The tool `project_deploy` takes the full path to the project and the Git revision to install. Obviously, this is not very useful, but easy to use in deployment hook scripts. You can find example PHP implementations for GitHub and GitLab web hooks in `webhook.github.php` and `webhook.gitlab.php`, but you can also create your own: 1. Write a script that receives web-hooks from GitHub, GitLab or similar and get the repository URL, commit SHA-1 and branch name of the event from the transmitted data. 2. Read the file `~/.projects`, which contains the paths to all known projects and sites, and iterate through it. 3. Open the projects `.origin` and `.branch` files. If they match the web-hook, run `project_deploy ` and you are done. ## Setup 1. Put this project wherever you want on the destination system and add the `bin` directory to your `PATH`. 2. Create a backup and clean your `DocumentRoot` (`/var/www/virtual//` on Uberspace), as you probably want to manage everything with this toolset. 3. Create a symlink to your `DocumentRoot` in `~/web` (this is what the `site_*` tools use): `ln -s /var/www/virtual/$USER/ ~/web` You can also link to a subdirectory of your `DocumentRoot` if you want to manage the sites of this tool separately from your other sites. Please note that the `site_link` functionality does not work without manually linking the resulting links to your `DocumentRoot` when using non-standard paths for `~/web`. 4. Have fun with the tools in `bin`. ## Configuration If you want to customize specific settings, you can create a Bash file at `~/.project.cnf` overriding the default values at every run of the tools. These are the possible settings and also the format of the file: # Default branch to set if no one is given to `project_origin` CONFIG_DEFAULT_BRANCH="master" # Allowed length of the parameter of `project_deploy` # Used to make deployments consistent (doesn't allow different hash lengths and therefore duplicated deployments) # Default is a full-length SHA-1 hash, use 7 as value when using short hashes. CONFIG_HASH_LENGTH=40 # Number of deployed versions to preserve (0 for infinite (be careful, that might use loads of storage space!)) # Versions older than the latest n versions get deleted automatically, logs are always preserved CONFIG_PRESERVE_VERSIONS=5 ## Author - Lukas Bestle ## License This project was published under the terms of the MIT license. You can find a copy [over at the repository](https://git.lukasbestle.com/tools/misc/blob/master/LICENSE.md).