Nginx expire dates for static files

If you are using nginx as proxy this snippet will help you set the correct expire dates for static files like css, jpg etc:

[code]location ~* \.(txt|xml|js)$ {
expires 8d;
}

location ~* \.(css)$ {
expires 8d;
}

location ~* \.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav|mp4|m4v|ogg|webm|aac)$ {
expires 8d;
}

location ~* \.(jpg|jpeg|png|gif|swf|webp)$ {
expires 8d;
}[/code]

This is will ensure the webserver to tell the browser that the served files are valid for 8 days and will not be downloaded again.

Rebuild your DirectAdmin user cache

In some particular cases I was unable to find my users using the DirectAdmin UI. Since then I use this little script to rebuild the user cache of the “Show All Users” list.

[code]#!/bin/sh

cd /usr/local/directadmin/data/users

for r in `ls */reseller.conf | cut -d/ -f1`; do
{
echo “fixing Reseller $r …”;

echo -n ” > $r/users.list

for u in `grep “^creator=$r$” */user.conf | cut -d/ -f1`; do
{
ISUSER=`grep -c usertype=user $u/user.conf`
if [ “$ISUSER” = “1” ]; then
echo $u >> $r/users.list
fi
};
done;
};
done;[/code]

After using this script all users will be shown again in DirectAdmin.

Nginx configuration for WordPress websites

If you are using the WP Super Cache plugin by Automattic, this configuration can help you settings up your Nginx caching proxy:

[code]proxy_cache_path /data/nginx/cache keys_zone=one:10m inactive=24h max_size=1G;
proxy_cache_key “$host$request_uri$cookie_user”;
proxy_cache one;

server {
server_name ~^(static\.)?(?.+)$;
access_log /var/log/nginx/domains/static.$domain.log;

location ~ ^/(wp-content|wp-includes)/ {
resolver 8.8.8.8;
expires 30d;
add_header Pragma public;
add_header Cache-Control “public”;
proxy_cache_valid 200 10m;
proxy_pass http://www.$domain;
add_header X-Cache-Status $upstream_cache_status;
}
}[/code]

Change the static.domain.com to the hostname the nginx server is listening to. Change domain.com (twice!) to the main domain where the content is pulled from.

Make a DNS record (either cname or a) pointing static.domain.com to the IP the nginx server is running at.

Be sure to chmod the /data/nginx/cache folder to 700 and change the ownership to the same user as nginx is running (default nginx).

Check if the cache is working by using this command:

[code]du -h –max-depth=1 /data/nginx/cache[/code]

Easy as that!

Remove e-mail sent count from e-mailaccount

If you want to reset the e-mail acount of a DirectAdmin account it’s pretty simple, you can just hit the reset button. But there are no such buttons for the e-mail accounts itself. So you can use this little line in SSH to remove the e-mail sent acount of a particular e-mail account:

rm -f /etc/virtual/domain.com/usage/info

Notice this line concerns info@domain.com. So you have to change the domain.com part and the info part.

Adding domain pointer with e-mail and SSL options

If you add a domain pointer to a DirectAdmin domain, you can not set-up the e-mail accounts and SSL certificates by default. Almost all the options are not available.

To fix this you can remove the domain pointer and add the domain as a normal domain to the account. It has to be the same account due to permissions.

Then, remove the private_html folder, symlink it to the public_html and set the correct permissions with this piece of code:

rm -rf /home/user/domains/domain.com/private_html
ln -s /home/user/domains/domain.com/public_html /home/user/domains/domain.com/public_html
chown -h user:user /home/user/domains/domain.com/public_html

Now you have the same effect of the normal Domain Pointer in DirectAdmin, but you are able to use the interface for all other DirectAdmin options!

Blocked from loading by Cross-Origin Resource Sharing policy

Sometimes with a multi-store or a multisite you have missing icons (fonts) or similarities.

If you get this error:

Font from origin ‘http://www.domain.com’ has been blocked from loading by Cross-Origin Resource Sharing policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://sub.domain.com’ is therefore not allowed access.

Add this to .htaccess file from www.domain.com and it will work again.

Header set Access-Control-Allow-Origin "*"

Extending HP smartarray with hpacucli

If you are trying to expend a raidset on a system with HP storage controllers you can use this.

Please note: you need to have a BBWC if you want to expand an array.

First check if the disks you added are detected:

hpacucli ctrl all config show

If you see the disks at the unassigned section we are good to go.

hpacucli ctrl slot=0 array A add drives=allunassigned

Get the slot and array information from the first output.
The expansion can take up allot of time. This is al depending on disk size and performance.

If the first process is done we need to set the logical disk to max space.

hpacucli ctrl slot=0 ld 1 modify size=max

If this is all done you probably need to expend your partition as well.

I would say, google is your friend!

 

Super easy lightweight router in AngularJS

I needed a lightweight routing component in one of my AngularJS projects. The existing solutions like UI router and the Angular Router are way to heavy for my requirements. I only had the following requirements:

  • One controller/view loaded for #pageA
  • Another controller/view loaded for #pageB

I decided to write my own router component, to be sure the routing component has an absolutely minimum footprint (around 2 kb, unminified).

The basic HTML structure:

<div ng-controller="RoutingController as router">
<div ng-if="router.route === 'pageA'" ng-controller="PageAController"></div>
<div ng-if="router.route === 'pageB'" ng-controller="PageBController"></div>
</div>

The RoutingController uses a Router factory and a RouterEventsService, and is defined like this:

function RoutingController($scope, Router, RoutingEventsService) {
    var controller = this;

    controller.route = 'pageA';

    var router = new Router;
    router.addRoute('pageA');
    router.addRoute('pageB');

    RoutingEventsService.listen(locationHashChanged);

    $scope.$on('$destroy', function() {
        RoutingEventsService.stop(locationHashChanged);
    });

    function locationHashChanged() {
        var currentRoute = router.route(window.location.hash);

        if (!currentRoute) {
            return false;
        }

        // scroll to top after switching route
        $('html,body').animate({scrollTop: 0}, 50);

        controller.route = currentRoute.name;
        $scope.$apply(); // RoutingEvents are defined outside the angular scope
    }
}

The Router factory function is defined like this:

function Router() {
    var m = this;

    m.routes = [];
    m.default = null;

    m.addRoute = function(name) {
        var route = {name: name};

        m.routes.push(route);

        if (!m.default) {
            m.default = route;
        }
    };

    m.getDefault = function() {
        return m.default;
    };

    m.route = function(hash) {
        var matched;

        angular.forEach(m.routes, function(route) {
            if (hash === '#/' + route.name) {
                matched = route;
            }
        });

        if (!matched) {
            matched = m.getDefault();
        }

        return matched;
    };
}

The RouterEventsService is defined like this:

function RoutingEventsService($window) {
    var service = this;

    service.listen = function(fn) {
        if ($window.addEventListener) {
            $window.addEventListener('load', fn);
            $window.addEventListener('hashchange', fn);
        } else if($window.attachEvent) {
            $window.attachEvent('load', fn);
            $window.attachEvent('hashchange', fn);
        }
    };

    service.stop = function(fn) {
        if ($window.removeEventListener) {
            $window.removeEventListener('load', fn);
            $window.removeEventListener('hashchange', fn);
        } else if($window.detachEvent) {
            $window.detachEvent('load', fn);
            $window.detachEvent('hashchange', fn);
        }
    };
}