Fork of manager for Subversion servers.
Go to file
Sergey Sharybin 9dec2d8927 Flatten the repository paths
Previous logic was adding an extra indirection level in the paths
which consists of 2 first letters of the repository name.

Since then the project was scaled down, and we only use it for own
needs, so it makes it simpler to simplify the paths.

Extra testing is needed, since something might be missing.
2023-05-13 20:32:50 +02:00
apache Use apachectl on FreeBSD 2023-05-13 18:54:44 +02:00
docker Web UI for managing repositories 2022-04-29 14:54:05 +00:00
filelocator Moved locating of files to its own package. 2017-11-02 12:55:23 +01:00
httphandler Web UI for managing repositories 2022-04-29 14:54:05 +00:00
json_schemas Allow email-like usernames 2017-12-22 14:29:38 +01:00
svnman Flatten the repository paths 2023-05-13 20:32:50 +02:00
ui Set default value for project ID and placeholder for creator 2022-05-02 13:13:51 +02:00
.dockerignore Add Dockerfile to simplify local setup 2022-04-29 13:45:44 +00:00
.gitignore Streamlined build process 2020-09-14 17:03:50 +02:00
CHANGELOG.md Added version 1.1 to changelog, and marked as released today 2020-09-15 10:17:22 +02:00
Dockerfile Update mock, fix go build -i deprecation error 2022-04-29 17:00:24 +02:00
go.mod Update mock, fix go build -i deprecation error 2022-04-29 17:00:24 +02:00
go.sum Update mock, fix go build -i deprecation error 2022-04-29 17:00:24 +02:00
gocheck_test.go Initial checkin of skeleton project with HTTP API routes 2017-10-20 16:51:18 +02:00
LICENSE.txt Initial checkin of skeleton project with HTTP API routes 2017-10-20 16:51:18 +02:00
main.go Web UI for managing repositories 2022-04-29 14:54:05 +00:00
Makefile Add package for FreeBSD 2023-05-13 18:14:27 +02:00
README.md Use apachectl on FreeBSD 2023-05-13 18:54:44 +02:00
run_docker.sh Add Dockerfile to simplify local setup 2022-04-29 13:45:44 +00:00
svn-manager.service Added build, deployment, and system integration scripts 2017-11-03 15:55:22 +01:00

SVN Manager

System requirements

Requirements are:

  • Apache 2
  • Mod-SVN

The SVNManager needs to be able to gracefully restart Apache after configuration files have been created. This is done by invoking sudo apache2ctl (or its equivalent on the OS - for example, apachectl when running on FreeBSD), and requires that this command can be performed without having to provide a password. Add the following to /etc/sudoers to set this up:

Cmnd_Alias GRACEFUL = /usr/sbin/apache2ctl configtest, /usr/sbin/apache2ctl graceful
www-data ALL = NOPASSWD: GRACEFUL

Replace www-data with the username of the SVNManager, and /usr/sbin/apache2ctl with the absolute path of that executable.

SVNManager tests that the command sudo --non-interactive apache2ctl configtest can be run successfully at startup. Failing to do so is considered a fatal error and will prevent SVNManager from starting.

Internal Structure

The HTTP interface is implemented in the httphandler subpackage. This package is responsible for interpreting the HTTP request by parsing variables from the URL and JSON sent in the body. Furthermore, it is responsible for validating these data.

The actual work managing on-disk files and directories is implemented in the svnman subpackage. This package assumes the data is vetted as correct by the httphandler subpackage.

Apache life cycles, at this moment consisting of graceful restarts, is handled by the apache subpackage.

Building a release

  • Install Golang. Make sure you unpack/install in a way that the current user can write to the Golang directory. This makes it possible to cross-compile the standard library without requiring tricks like Docker containers.
  • Install zip
  • Install mockgen
  • Run make mocks test
  • Tag the version: git tag v1.3
  • Run make package

Installation

Server preparation

  • SVN repositories are to be stored in /data/svn/repos; If this changes, remember this and update svn-manager.service in the section below.
  • Install Apache + mod-svn + subversion: sudo apt install apache2 libapache2-mod-svn subversion
  • Create the SVN repo directory and set permissions: sudo mkdir -p /data/svn/repos; sudo chown www-data:www-data /data/svn/repos; sudo chmod 2775 /data/svn/repos
  • Enable Apache modules: sudo a2enmod deflate dav dav_svn authz_svn headers proxy proxy_http
  • Make a directory for the SVN Apache config: sudo mkdir /etc/apache2/svn; sudo chown www-data:www-data /etc/apache2/svn; sudo chmod 0775 /etc/apache2/svn
  • Create the API passwords file: sudo htpasswd -B -c /etc/apache2/api-htpasswd someusername. If the file already exists, drop the -c argument.
  • Set the API passwords file permissions: sudo chown root:www-data /etc/apache2/api-htpasswd; sudo chmod 0640 /etc/apache2/api-htpasswd
  • Update /etc/apache2/sites-available/000-default.conf:
<VirtualHost *:80>
    ServerAdmin your@email.address
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # Work around TLS termination being done by the TransIP HA-IP, and not by this server:
    RequestHeader edit Destination ^https: http:

    IncludeOptional svn/*.conf
    IncludeOptional svn/*/*.conf

    <Location /api/>
        AuthType Basic
        AuthName "Blender Cloud SVN Manager API"
        AuthUserFile api-htpasswd
        Require valid-user
        ProxyPass http://[::1]:8085/api/
        ProxyPassReverse http://[::1]:8085/api/
    </Location>

    <Location /manage/>
        AuthType Basic
        AuthName "Blender Cloud SVN Manager"
        AuthUserFile api-htpasswd
        Require valid-user
        ProxyPass http://127.0.0.1:8085/manage/
        ProxyPassReverse http://127.0.0.1:8085/manage/
    </Location>
</VirtualHost>
  • Restart Apache: sudo systemctl restart apache2
  • Put a nice message in /var/www/html/index.html so that it doesn't show the default Ubuntu "It Works!" page.

Using Docker for local setup

In case you'd like to run an SVN manager without going through the whole setup listed above, you can use a container described by the Dockerfile.

To build and run it, use the following command:

./run_docker.sh

This will build an image and start a container running Apache2, and then build and start SVN manager inside this container.

It will have a single API user: admin with an empty password.

In order to restart just the SVN manager (e.g. after changing the go modules), stop the script (the container will remain running), then rebuild and restart SVN manager using the following:

docker exec --user www-data:www-data -it svn-manager go run main.go -verbose -repo /data/svn/repos

In order to rebuild the image and restart the container (e.g. after changing Apache configuration), stop the script and run it again.

Building and installing SVN-Manager

  • In the SVN-Manager's source directory, run make package to build the checked-out version.
  • Copy dist/svn-manager-v1.0-linux.tar.gz to the server. The version number may be different, of course.
  • Become root: sudo su -
  • Extract the tarball to /opt, this will create /opt/svn-manager-v1.0.
  • Create or update the symlink cd /opt; rm -f svn-manager; ln -s svn-manager-v1.0 svn-manager
  • Grant 'sudo' permissions, by adding this to /etc/sudoers (via visudo):
Cmnd_Alias GRACEFUL = /usr/sbin/apache2ctl configtest, /usr/sbin/apache2ctl graceful
www-data ALL = NOPASSWD: GRACEFUL
  • Install the service: cp /opt/svn-manager/svn-manager.service /etc/systemd/system/svn-manager.service
  • Update the service and set ExecStart=/opt/svn-manager/svn-manager -verbose -repo /data/svn/repos
  • Enable and start the service: sudo systemctl daemon-reload; sudo systemctl enable svn-manager; sudo systemctl start svn-manager

To see the logs from SVN Manager, use journalctl -u svn-manager

Testing the installation

Run this command to test the installation. It assumes the username and password have been given access with sudo htpasswd -B /etc/apache2/api-htpasswd apiuser and password apipassword.

curl -v -u apiuser:apipassword https://server-address/api/nonexistant

If the Apache part of the installation was correct, and the SVN Manager is running, this should produce a 404 Not Found error (and not a 500 Internal Server).

curl -v -u apiuser:apipassword \
    --data '{"repo_id": "one_two_three", "project_id": "59eefa9cf488554678cae036", "creator": "You <you@example.com>"}' \
    -H 'Content-Type: application/json' \
    https://server-address/api/repo

This should return a 201 Created response, with a Location: /api/repo/one_two_three header in there.

curl -v -u apiuser:apipassword \
    https://server-address/api/repo/one_two_three

This should return {"repo_id":"one_two_three","access":[]}, indicating that nobody has access.

curl -v -u apiuser:apipassword \
    --data '{"grant": [{"username": "you", "password": "$2y$05$sF.twcpdlcu76/KVgAuCPe.t5UYxDCKREnse74vPNqVYRYfO/9Wz6"}]}' \
    -H 'Content-Type: application/json' \
    https://server-address/api/repo/one_two_three/access

This should return an empty 200 OK reponse.

Now you can do an SVN checkout with username 'you' and password 'rock':

svn co https://server-address/repo/one_two_three