Skip to main content

Setting up a Git Server in CentOS 6.5

Install git.

[[email protected] ~]# yum install git

Add the developers group, all git users will be part of this group.

[[email protected] ~]# groupadd developers

Create the git user which will own all the repos.

[[email protected] ~]# useradd -s /sbin/nologin -g developers git
[[email protected] ~]# passwd git
Changing password for user git.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

Update Permissions.

[[email protected] ~]# chmod 2770 /home/git/

Create an empty Git repo.

[[email protected] project1]# git init --bare --shared
Initialized empty shared Git repository in /home/git/project1/

Update file ownership and permissions.

[[email protected] project1]# chown -R git .
[[email protected] project1]# chmod 2770 /home/git/project1

Create a git user account.

[[email protected] git]# useradd -s /usr/bin/git-shell -g developers -d /home/git tony
useradd: warning: the home directory already exists.
Not copying any file from skel directory into it.
[[email protected] git]# passwd tony
Changing password for user tony.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

At this point a regular user should be able to checkout the project1 repo from the Git server.

[email protected]:~$ mkdir ~/testing_shit/git_test
[email protected]:~$ cd ~/testing_shit/git_test && git init
[email protected]:~/testing_shit/git_test$ git remote add origin [email protected]:/home/git/project1

Note:
Interestingly enough, an initial first commit has to be made onto the repo in order for any regular user to be able to push the repo, ie master branch. I received the following error when trying do so.

[email protected]:~/testing_shit/git_test$ git push origin master
[email protected]'s password:
error: src refspec master does not match any.
error: failed to push some refs to '[email protected]:/home/git/project1'

Fix:

[email protected]:~/testing_shit/git_test$ git commit -m 'Initial'
[master (root-commit) 7bb7337] Initial
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.txt

[email protected]:~/testing_shit/git_test$ git push origin master
[email protected]'s password:
Counting objects: 3, done.
Writing objects: 100% (3/3), 209 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To [email protected]:/home/git/project1
* [new branch] master -> master

Linux: 

Awesome Applications: 

Securing the WordPress Admin Dashboard

So the primary reason why I wanted to add SSL support to www.rubyninja.org is because I want all my /wp-admin traffic to be served securely.

Configuring WordPress to force the login page and all wp-admin traffic to be served over SSL is simply just a matter of defining the FORCE_SSL_LOGIN and FORCE_SSL_ADMIN constants in wp-config.php

define( 'FORCE_SSL_LOGIN', true );
define( 'FORCE_SSL_ADMIN', true );

Programming: 

Awesome Applications: 

Reverse SSL Proxy with Nginx

Nginx is turning to be an awesome SSL reverse proxy server, although I can't say I've really put it to real heavy duty use or how it well scale since my sites have relatively slow traffic. Thus said, a reverse SSL proxy using Nginx is working flawless in my environment!

Since all of my sites are being served within a KVM guest using NAT networking, all SSL traffic has to go through the KVM host of which Nginx is being used to proxy the requests to the guest KVM. Nginx is awesome since it supports specifying multiple server blocks (think of virtul hosts in Apache) set to listen on port 443 within the main http block. With this configuration available, it is possible to specify different reverse proxy end points.

On my server I have enabled SSL for www.rubysecurity.org and www.rubyninja.org.

First thing I needed to do is to map the sites local IPs to the KVM hosts file.

192.168.100.208 rubysecurity.org www.rubysecurity.org
192.168.100.209 rubyninja.org www.rubyninja.org

Then configure nginx.conf (sample server blocks):

server {
        listen       443;
        server_name  www.rubysecurity.org;
        ssl                 on;
        ssl_certificate     /etc/nginx/certs/www.rubysecurity.org.bundled.crt;
        ssl_certificate_key /etc/nginx/certs/www.rubysecurity.org.key;


        location / {
            proxy_pass   https://www.rubysecurity.org;
	    
		    ### Set headers ####
            proxy_set_header        Accept-Encoding   "";
	        proxy_set_header        Host            $host;
	        proxy_set_header        X-Real-IP       $remote_addr;
	        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
 
		    #proxy_set_header X-Forwarded-Proto https;##
		    #This is better##
	        proxy_set_header        X-Forwarded-Proto $scheme;
		    add_header              Front-End-Https   on;
 
            # We expect the downsteam servers to redirect to the right hostname, so don't do any rewrites here.
            proxy_redirect     off;
        }
    }

 	server {
        	listen   443;
        	server_name www.rubyninja.org;
        	ssl on;
        	ssl_certificate     /etc/nginx/certs/www.rubyninja.org.bundled.crt;
        	ssl_certificate_key /etc/nginx/certs/www.rubyninja.org.key;

	    location / {
            proxy_pass   https://www.rubyninja.org;

            ### Set headers ####
            proxy_set_header        Accept-Encoding   "";
            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

            #proxy_set_header X-Forwarded-Proto https;##
            #This is better##
            proxy_set_header        X-Forwarded-Proto $scheme;
            #add_header              Front-End-Https   on;

            # We expect the downsteam servers to redirect to the right hostname, so don't do any rewrites here.
            proxy_redirect     off;
        }

One interesting thing in Nginx with SSL is that it doesn't have a dedicated Certificate Authority (CA) ssl certificate directive, unlike SSLCACertificateFile in Apache. Instead the CA certificate has to be bundled with the public ssl certificate, which it's really not a big deal given that multiple CA's tend to bundle their intermediate CA certificates similarly.

Linux: 

Awesome Applications: 

Problems installing Chrome on OpenSuSE 13.1

Error:

linux-5n99:/home/tony/Downloads # rpm -ivh google-chrome-stable_current_x86_64.rpm
warning: google-chrome-stable_current_x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 7fac5991: NOKEY
error: Failed dependencies:
lsb >= 4.0 is needed by google-chrome-stable-31.0.1650.63-1.x86_64

Fix:

linux-5n99:/home/tony/Downloads # yast --install lsb

Linux: 

Awesome Applications: 

Password protecting single user mode

I was surprise to find out how easy it was to password protect runlevel 1 aka single user mode in RHEL/CentOS.

Simply update the SINGLE variable in the file /etc/sysconfig/init

SINGLE=/sbin/sulogin

Single User mode password protected

If the root password cannot be retrieved/reset, then at this point the only option will be to boot into a rescue environment, assuming encryption hasn't been enabled.

Password protecting GRUB in RHEL/CentOS

Specifying a password to modify GRUB during the boot start-up phase can be initially set during the install, but it can also be manually added and or modified after the installation.

Using the grub-md5-crypt utility, you can generate an md5 hashed password (some security better than no security).

[[email protected] ~]# grub-md5-crypt
Password:
Retype password:
$1$/dvPV1$ngGsOO21eHj2lzEk7wg9d0

Now, is just a matter of adding the following entry in /boot/grub/grub.conf

password --md5 $1$/dvPV1$ngGsOO21eHj2lzEk7wg9d0

Restart, and voala.
GRUB image

Linux: 

Varnish WordPress Performance Testing

Thanks to my new job, I've been working a lot with Varnish. Man, Varnish is one kick ass HTTP web accelerator! A few months back I ran a few performance Apache performance tests on my WordPress site with different layers of caching enabled:
https://www.rubysecurity.org/php_xcache
https://www.rubysecurity.org/apache_stress-testing

So now I wanted to see how the results may differ using Varnish.

Configuration:
At a bare minimal, Varnish needs to be configured to remove cookies set by WordPress in order to make the content cacheable.

sub vcl_recv {
  # Drop any cookies sent to Wordpress.
  if (!(req.url ~ "wp-(login|admin)") && req.http.host ~ "rubyninja.org") {
    unset req.http.cookie;
  }
}

sub vcl_fetch {
  # Drop any cookies Wordpress tries to send back to the client.
  if (!(req.url ~ "wp-(login|admin)") && req.http.host ~ "rubyninja.org") {
    unset beresp.http.set-cookie;
  }
}

With this configuration enabled, I ran the same identical ab tests that used to benchmark my server previously.

[[email protected] ~]# ab -n 1000 -c 5 http://www.rubyninja.org/index.php
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking www.rubyninja.org (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests

Server Software: Apache/2.2.15
Server Hostname: www.rubyninja.org
Server Port: 80

Document Path: /index.php
Document Length: 0 bytes

Concurrency Level: 5
Time taken for tests: 39.528015 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Non-2xx responses: 1001
Total transferred: 374139 bytes
HTML transferred: 0 bytes
Requests per second: 25.30 [#/sec] (mean)
Time per request: 197.640 [ms] (mean)
Time per request: 39.528 [ms] (mean, across all concurrent requests)
Transfer rate: 9.23 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 87 100 134.1 93 3092
Processing: 88 95 10.7 91 220
Waiting: 87 94 10.6 90 218
Total: 177 196 134.4 186 3183

Percentage of the requests served within a certain time (ms)
50% 186
66% 192
75% 196
80% 199
90% 207
95% 217
98% 234
99% 251
100% 3183 (longest request)

The requests per second handled by the webserver weren't much different from the caching layer that I already had enabled previously, which is the WordPress W3 Total Cache plugin configured with Page, Database, Object, and Browser cache enabled using APC, and mod_pagespeed.

However the huge difference is that all requests never reached the Apache backend. Varnish cached all content and served all the requests directly. Varnish is just fucking awesome.

Awesome Applications: 

Leaving Gmail and Google Apps: Part I

Since I'm paying for essentially unmaged dedicated hosting so I can run my mail server. I opted to consolidate my personal web applications to the same physical box. This is why I created a KVM guest that would solely be used for my web traffic. One of the main challenges I'm faced is the fact that I only have one public IP address. This means that all of my KVM guests have been configured using the default NAT networking.

For all http traffic I'm using Varnish as the proxy and caching server and for https traffic I'm using Nginx.
http_architecture

First thing that broke using this different architecture on my sites are the mod_access IP restrictions that I originally had set in place previously. This is becuase the Apache backend see's all requests originating from the Varnish and Nginx proxies. Luckily both Varnish and Nginx have really simple access control mechanism built in them.

For example, in Varnish I can create a list of IPs that I can use to their block or grant access to certain URLs.

acl admin {
   "localhost";
    "MyPublicIPAddress";
} 

sub vcl_recv {
  # Only allow access to the admin ACL
  if (req.url ~ "^/secureshit" && req.http.host ~ "rubysecurity.org") {
    if (client.ip ~ admin) {
      return(pass);
    } else {
      error 403 "Not allowed in admin area.";
    }
  }
}

Nginx acl

location  /secureshit {
  allow MyPublicIPAddres;
  deny all;
  proxy_pass https://www.rubysecurity.org/secureshit;
}

Linux: 

Awesome Applications: 

Leaving Gmail and Google Apps

Ever since finding out about Google's involvement in PRISM a few months back, I've been wanting to completely ditch their Gmail and Google Docs services for good. Having used those services for such a long time, and more importantly them being free (as in beer), deciding which new platform I would use as the replacement was my first challenge. Firstly, all email services will be managed by me solely. So my first task was to find a reliable, and perhaps more importantly, a really cheap unmanaged dedicated hosting provider. I opted to go with OVH. Having first heard of OVH on a Linux Journal advertisement, I became completely sold on their $29.99 a month dedicated hosting offering. Even better, OVH is not an American company and they themselves having to deal with lots of scrutiny for hosting WikiLeaks. The really cheap $29.99 dedicated hosting plan does have a catch, the hardware is not enterprise quality server hardware, but rather desktop hardware. The disk is not RAIDed, and the memory is non ECC. Personally, since I don't believe my server will have much heavy load, I really don't see this as a problem. Additionally, using my home Nagios monitoring server and with the help of NRPE, I'm going to monitoring just about everything on the dedicated machine.

My current hypothetical architecture:

Install configure KVM on the system, and run three virtual machine instances.
The host machine will have the following:

  • Varnish, to proxy all HTTP traffic.
  • Nginx, to proxy all HTTPS traffic.
  • Proxy POP/IMAP mail traffic using iptables (if this does not work as I expect, I might look into using haproxy instead)

1). VM 1: http

  • Apache PHP/Ruby, all of my web apps will be using on this VM. (including this site itself)

2). VM 2: database

  • MySQL
  • PostgreSQL

3). VM 3: email

  • Postfix for sending mail
  • Dovecot for receiving mail

Enabling SMART on a hard drive

Error:

[[email protected] ~]# smartctl -H /dev/sdb
smartctl 5.43 2012-06-30 r3573 [x86_64-linux-2.6.32-358.23.2.el6.x86_64] (local build)
Copyright (C) 2002-12 by Bruce Allen, http://smartmontools.sourceforge.net

SMART Disabled. Use option -s with argument 'on' to enable it.

Fix:

[[email protected] ~]# smartctl -s on /dev/sdb
smartctl 5.43 2012-06-30 r3573 [x86_64-linux-2.6.32-358.23.2.el6.x86_64] (local build)
Copyright (C) 2002-12 by Bruce Allen, http://smartmontools.sourceforge.net

=== START OF ENABLE/DISABLE COMMANDS SECTION ===
SMART Enabled.

Awesome Applications: 

Pages

Premium Drupal Themes by Adaptivethemes