Django + Gunicorn + Nginx Setup

Prior to gunicorn and nginx, i’ve tried to user apache + mod_wsgi and failed. Still don’t know why it fail. After 3 days trying, I give up. I have to look for another method, I try using gunicorn dan nginx, and It took me only 2 days for gunicord + nginx setup to works. 🙂

Here is condition on my Django + Gunicorn + Nginx setup:

  • I use CentOS 7 on my server
  • I create new user for running django (in my case /home/myuser)
  • I install python 3.7.3, django, pandas, django_extensions, virtual environment, gunicorn dan nginx
  • My django project folder is /home/myuser/myproject
  • I put all my django app (created using ‘python manage.py startapp myapp apps/myapp’) in /home/myuser/myproject/apps

Here is some of reference I use:

Here is my setup:

/home/myuser/myproject/wsgi.py

import os
import sys

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
sys.path.append('/home/myuser/myproject/apps')

application = get_wsgi_application()

/etc/nginx/nginx.conf

user  nginx; 
worker_processes  1; 

error_log  /var/log/nginx/error.log warn; 
pid        /var/run/nginx.pid; 


events { 
   worker_connections  1024; 
} 


http { 
   include       /etc/nginx/mime.types; 
   default_type  application/octet-stream; 

   log_format  main  '$remote_addr - $remote_user [$time_local] "$request" ' 
                     '$status $body_bytes_sent "$http_referer" ' 
                     '"$http_user_agent" "$http_x_forwarded_for"'; 

   access_log  /var/log/nginx/access.log  main; 

   sendfile        on; 
   #tcp_nopush     on; 

   keepalive_timeout  65; 

   #gzip  on; 

   include /etc/nginx/conf.d/*.conf; 
}

/etc/systemd/system/gunicorn.service

setup for gunicorn to be run as service.

[Unit] 
Description=gunicorn service 
After=network.target 

[Service] 
User=myuser 
Group=myuser 
WorkingDirectory=/home/myuser/myproject/ 
ExecStart=/home/myuser/app1/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/myuser/myproject/myproject.sock myproject.wsgi:application --log-level debug 

[Install] 
WantedBy=multi-user.target

don’t forget to enable service using:

systemctl enable gunicorn

/home/myuser/myproject/myproject/setting.py

import os 

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 

SECRET_KEY = '6sp(_!o*NOT_MY_REAL_KEY_OF_COURSE*uu5o(9q1+ir=:-)r' # change: my key

DEBUG = True # to be changed on production

ALLOWED_HOSTS = ['my_ip','myuser.mydomain.com'] #change: my_ip & my domain


# Application definition 

INSTALLED_APPS = [ 
   'django.contrib.admin', 
   'django.contrib.auth', 
   'django.contrib.contenttypes', 
   'django.contrib.sessions', 
   'django.contrib.messages', 
   'django.contrib.staticfiles', 
   'django.contrib.humanize', 
   'django_extensions', 
   'myproject', 
   'myproject.templatetags', # delete:my custom tags
   'login', # delete:my app
   'weeklyreport', # delete:my app
]
MIDDLEWARE = [ 
   'django.middleware.security.SecurityMiddleware', 
   'django.contrib.sessions.middleware.SessionMiddleware', 
   'django.middleware.common.CommonMiddleware', 
   'django.middleware.csrf.CsrfViewMiddleware', 
   'django.contrib.auth.middleware.AuthenticationMiddleware', 
   'django.contrib.messages.middleware.MessageMiddleware', 
   'django.middleware.clickjacking.XFrameOptionsMiddleware', 
] 

ROOT_URLCONF = 'myproject.urls' 

TEMPLATES = [ 
   { 
       'BACKEND': 'django.template.backends.django.DjangoTemplates', 
       'DIRS': ['my_templates'],  #change
       'APP_DIRS': True, 
       'OPTIONS': { 
           'context_processors': [ 
               'django.template.context_processors.debug', 
               'django.template.context_processors.request', 
               'django.contrib.auth.context_processors.auth', 
               'django.contrib.messages.context_processors.messages', 
           ], 
       }, 
   }, 
] 

WSGI_APPLICATION = 'myproject.wsgi.application' 


DATABASES = { 
   'default': { #change: my database setup
       'ENGINE': 'django.db.backends.mysql', 
       'NAME': 'mydb1', 
       'USER': 'myuseruser', 
       'PASSWORD': 'my_db_password', 
       'HOST': '192.168.0.2', 
       'OPTIONS': { 
           'read_default_file': '/etc/my.cnf.d/client.cnf', 
           'init_command': "SET sql_mode='STRICT_TRANS_TABLES'; SET SESSION binlog_format = 'ROW';", 
       },
        'jgmotordb': { #delete: my database setup
       'ENGINE': 'django.db.backends.mysql', 
       'NAME': 'mydb2',  #change
       'USER': 'myuseruser', #change
       'PASSWORD': 'my_db_password',  #change
       'HOST': 'my_ip', # change
       'OPTIONS': { 
           'read_default_file': '/etc/my.cnf.d/client.cnf', 
           'init_command': "SET sql_mode='STRICT_TRANS_TABLES'; SET SESSION binlog_format = 'ROW';", 
           } 
       }
   } 
}

AUTH_PASSWORD_VALIDATORS = [ 
   { 
       'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 
   }, 
   { 
       'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 
   }, 
   { 
       'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 
   }, 
   { 
       'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 
   }, 
] 

LANGUAGE_CODE = 'en-us' 
TIME_ZONE = 'UTC' 
USE_I18N = True 
USE_L10N = True 
USE_TZ = True 

STATIC_URL = '/static/' # my static folder
STATICFILES_DIRS = [ 
   os.path.join(BASE_DIR, '0static'),  # my static folder (before for 'collectstatic' command)
] 
STATIC_ROOT = os.path.join(BASE_DIR, 'static') 
AUTHENTICATION_BACKENDS = ( 'myproject.backend.custombackend', ) #delete: my custom backends

It’s my django project. Therefor, you might find my setup is not ideal, but it works! 🙂 (and it took me a week to make it works).

I learn that, most of tutorials use aptapt-get for installation. Since I use CenOS (which use yum as default) I find it annoying. 😦

Please leave a comment for any suggestion or if you find this post helpful.

Coding Wisdom #1

  1. If it’s not tested, it doesn’t work.
  2. Source control is your friend – make sure you use it.
  3. Just because you wrote it doesn’t mean you own it — don’t be offended if someone else on your team has to change your code.
  4. Don’t reinvent the wheel, library code is there to help.
  5. The fastest code is code that’s never executed — look for early outs.
  6. Just because you didn’t write it doesn’t mean it’s crap.
  7. Source code is just a hint to the compiler about what you want to do, it won’t necessarily do it (e.g. You might declare a function as inline but the compiler doesn’t have to obey).
  8. Code that’s hard to understand is hard to maintain.
  9. Code that’s hard to maintain is next to useless.
  10. “Whilst I’m editing this file I’ll just…” is a great way to introduce feature creep and bugs.
  11. The neater your code layout, the easier it is to read. The easier it is to read, the easier it is to understand and maintain.
  12. Code is not self documenting. Help others by adding comments to guide them. You may understand it now but what about in 5 years time?
  13. Bad Code can and will come back to haunt you.
  14. There is no such thing as a 5 minute job. It’ll always take at least half a day.
  15. Magic numbers are bad.
  16. Constants don’t take up storage, they’re compile time text substitutions.
  17. Project management will always want you to do twice as much in half the time.
  18. If there is a bug, the user will find it.
  19. A code review is not a criticism.
  20. It’s not the quantity of code that matters, it’s the quality. Any idiot can bang out 40k line of code but that doesn’t make it fit for purpose.
  21. The true cost of poorly written code is in the maintenance.
  22. Eat your own dog food — fixing bugs in your own code helps you code better and improves your understanding.
  23. Code rots over time.
  24. If the user didn’t ask for a feature, don’t add it.
  25. If it’s not tested, it doesn’t work (yes, I know I’ve included that twice but it’s really important)

Quoted from: Drew Eckhardt @ What are some of the most basic things every programmer should know?

Setting Multiple Domain Mail Server Menggunakan POSTFIX + DOVECOT + CYRUS-SASL + MYSQL

Saya percaya, akan ada saat dimana setting mail server di linux semudah instalasi MS Exchange Server di windows. Tapi saat itu bukan hari ini …

Instalasi aplikasi di server linux memang memiliki kesulitan tersendiri. Kalau pun kita sudah “pernah”, pas dicoba 1x lagi pada distro yang berbeda atau walau cuma beda versi, belum tentu hasilnya sama.

Pertama kali saya melakukan instalasi mail server adalah 2 tahun lalu saya melakukan instalasi mail server diatas OS Linux Fedora 9, cara mudahnya adalah dengan cara copas dari berbagai tutorial yang saya termukan di internet. Alhasil, setelah 1 minggu usah, punya juga mail server. Sekarang, saya coba lagi melakukan yang sama pada Fedora 14. Cara praktisnya adalah copas konfigurasi server lama ke server baru. Tapi ternyata … memang tidak semudah yang dikira. Beberapa perbedaan versi pada aplikasi yang dipakai menjadikannya perlu ada adaptasi agar konfigurasi lama yang saya pakai bisa digunakan kembali.

Berikut adalah beberapa catatan yang saya buat pada saat melakukan konfigurasi Mail Server dengan Multiple Domain (Virtual Domain) di Linux.

Jika Anda pernah melakukan instalasi email server menggunakan MS Exchange Server, semuanya mudah. 1 program untuk seluruh keperluan. Berbeda dengan Linux, Mail Server terdiri dari program yang terpisah. Dengan demikian, untuk bisa memahaminya tentunya harus mengetahui fungsi masing-masing program yang digunakan.

Berikut adalah spesifikasi Mail Server yang saya buat:
Dibuat diatas OS Linux Fedora 14.
Mail server terdiri dari POSTFIX, Dovecot, Cyrus-SASL, MySQL.
Virtual domail: example.com & example2.com
Mengirim email menggunakan authentikasi PLAIN (artinya password tidak di enkripsi)
authentikasi POP & IMAP menggunakan LOGIN PLAIN (artinya password tidak di enkripsi)

POSTFIX
POSTFIX adalah program yang berfungsi menerima dan mengirim email.
instalasi modul yang diperlukan untuk POSTFIX adalah:
yum install postfix

berikut adalah initial setting untuk POSTFIX yang saya gunakan (file: /etc/postfix/main.cf)

# uncomment for debugging if needed
soft_bounce=yes
debug_peer_level = 99
debug_peer_list = 127.0.0.1

# postfix main
mail_owner = postfix
setgid_group = postdrop
delay_warning_time = 4

# postfix paths
html_directory = no
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
queue_directory = /var/spool/postfix
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
manpage_directory = /usr/share/man

# network settings
inet_interfaces = all
mydomain = example.com
myhostname = host.example.com
mydestination = $myhostname localhost.$mydomain
mynetworks = 127.0.0.0/8, 119.235.30.174/32
mynetworks_style = subnet
myorigin = example.com
relay_domains = example2.com #virtual domain

# mail delivery
recipient_delimiter = +

# mappings
alias_maps = mysql:/etc/postfix/mysql-aliases.cf

# virtual setup
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_alias_maps.cf
virtual_gid_maps = static:89
virtual_mailbox_base = /home/vmail
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf
virtual_minimum_uid = 89 #UID user postfix. lihat di file /etc/group
virtual_transport = virtual
virtual_uid_maps = static:89 #UID user postfix. lihat di file /etc/group

# debugging
debug_peer_level = 5
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
xxgdb $daemon_directory/$process_name $process_id & sleep 5

# authentication
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
broken_sasl_auth_clients = yes

smtpd_helo_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_invalid_hostname
smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination,
reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain,
reject_unverified_sender, reject_unverified_recipient

smtpd_helo_required = yes
unknown_local_recipient_reject_code = 550
disable_vrfy_command = yes
smtpd_data_restrictions = reject_unauth_pipelining
message_size_limit = 12582912

Seperti yang saya ungkapkan sebelumnya, ini adalah initial setup. Artinya konfigurasi “asal jalan”. Untuk keamanan, tentunya konfigurasi tersebut harus di tweak lagi.

informasi yang menghubungkan antara POSTFIX dengan mysql diletakan pada file *.cnf. Isi dari file-file tersebut adalah sebagai berikut:
/etc/postfix/mysql-aliases.cf
user = postfix
password = mypassword
dbname = postfix
table = postfix_alias
select_field = destination
where_field = alias
hosts = localhost

/etc/postfix/mysql-virtual_alias_maps.cf
hosts = localhost
user = postfix
password = mypassword
dbname = postfix
table = alias
select_field = goto
where_field = address

/etc/postfix/mysql-virtual_domains_maps.cf
hosts = localhost
user = postfix
password = buburayam
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '0' and active = '1'

/etc/postfix/mysql-virtual_mailbox_maps.cf
hosts = localhost
user = postfix
password = buburayam
dbname = postfix
table = mailbox
select_field = maildir
where_field = username

MySQL
Ada banyak cara bagaimana Anda menyimpan data username & password. Namun untuk kali ini, saya memilih menggunakan MySQL.
instalasi modul yang diperlukan untuk MySQL adalah:
yum install mysql mysql-server

Buat database yang akan digunakan menggunakan SQL berikut:

CREATE TABLE IF NOT EXISTS `admin` (
`username` varchar(255) NOT NULL DEFAULT '',
`password` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`username`)
);

CREATE TABLE IF NOT EXISTS `alias` (
`address` varchar(255) NOT NULL DEFAULT '',
`goto` text NOT NULL,
`domain` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`address`)
);

CREATE TABLE IF NOT EXISTS `alias_domain` (
`alias_domain` varchar(255) NOT NULL DEFAULT '',
`target_domain` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`alias_domain`),
KEY `active` (`active`),
KEY `target_domain` (`target_domain`)
) ;

CREATE TABLE IF NOT EXISTS `config` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '',
`value` varchar(20) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `domain` (
`domain` varchar(255) NOT NULL DEFAULT '',
`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`aliases` int(10) NOT NULL DEFAULT '0',
`mailboxes` int(10) NOT NULL DEFAULT '0',
`maxquota` bigint(20) NOT NULL DEFAULT '0',
`quota` bigint(20) NOT NULL DEFAULT '0',
`transport` varchar(255) DEFAULT NULL,
`backupmx` tinyint(1) NOT NULL DEFAULT '0',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`domain`)
);

CREATE TABLE IF NOT EXISTS `domain_admins` (
`username` varchar(255) NOT NULL DEFAULT '',
`domain` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL DEFAULT '1',
KEY `username` (`username`)
);

CREATE TABLE IF NOT EXISTS `fetchmail` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`mailbox` varchar(255) NOT NULL DEFAULT '',
`src_server` varchar(255) NOT NULL DEFAULT '',
`src_auth` enum('password','kerberos_v5','kerberos','kerberos_v4','gssapi','cram-md5','otp','ntlm','msn','ssh','any') DEFAULT NULL,
`src_user` varchar(255) NOT NULL DEFAULT '',
`src_password` varchar(255) NOT NULL DEFAULT '',
`src_folder` varchar(255) NOT NULL DEFAULT '',
`poll_time` int(11) unsigned NOT NULL DEFAULT '10',
`fetchall` tinyint(1) unsigned NOT NULL DEFAULT '0',
`keep` tinyint(1) unsigned NOT NULL DEFAULT '0',
`protocol` enum('POP3','IMAP','POP2','ETRN','AUTO') DEFAULT NULL,
`ssl` tinyint(1) unsigned NOT NULL DEFAULT '0',
`extra_options` text,
`returned_text` text,
`mda` varchar(255) NOT NULL DEFAULT '',
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `log` (
`timestamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`username` varchar(255) NOT NULL DEFAULT '',
`domain` varchar(255) NOT NULL DEFAULT '',
`action` varchar(255) NOT NULL DEFAULT '',
`data` varchar(255) NOT NULL DEFAULT '',
KEY `timestamp` (`timestamp`)
);

CREATE TABLE IF NOT EXISTS `mailbox` (
`username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`maildir` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`quota` bigint(20) NOT NULL DEFAULT '0',
`domain` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`passwd_expire` char(1) COLLATE utf8_unicode_ci NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`username`)
);

CREATE TABLE IF NOT EXISTS `postfix_alias` (
`destination` varchar(50) DEFAULT NULL,
`alias` varchar(50) DEFAULT NULL
);

CREATE TABLE IF NOT EXISTS `vacation` (
`email` varchar(255) NOT NULL DEFAULT '',
`subject` varchar(255) NOT NULL DEFAULT '',
`body` text NOT NULL,
`cache` text NOT NULL,
`domain` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`email`),
KEY `email` (`email`)
);

Dovecot
POSTFIX hanya bertugas menerima dan mengirim. Sedangkan program yang melayani aplikasi email client lewat protokol IMAP & POP (seperti MS Outlook, Mozilla Thunderbird atau SquirellMail) ditangani oleh Dovecot.
instalasi modul yang diperlukan untuk Dovecot adalah:
yum install dovecot dovecot-mysql

konfigurasi untuk dovecot (saya menggunakan versi 2) terletak di dalam file /etc/dovecot/dovecot.conf, dan dari file tersebut load file lain yang ada di /etc/dovecot/conf.d. Namun untuk penyerderhanaan, saya membuatnya menjadi 1 file di /etc/dovecot/dovecot.conf dengan isi sebagai berikut:

# 2.0.9: /etc/dovecot/dovecot.conf
# OS: Linux 2.6.35.6-45.fc14.x86_64 x86_64 Fedora release 14 (Laughlin) ext3
first_valid_uid = 89
log_path = /var/log/dovecot

disable_plaintext_auth = no

#debug option
#mail_debug = yes
#auth_debug_passwords=yes
#auth_debug=yes
#auth_verbose = yes
#auth_verbose_passwords=plain
#verbose_ssl = yes

mail_location = maildir:/home/vmail/%d/%n
protocols = pop3 imap
ssl_cert =

Dovecot pun perlu sambungan untuk membaca informasi user yang tersimpan di MySQL. Konfigurasi untuk koneksi ke MySQL bisa dilihat di /etc/dovecot/dovecot-mysql.conf

driver = mysql
connect = host=localhost dbname=postfix user=postfix password=mypassword
default_pass_scheme = PLAIN

password_query = SELECT password FROM mailbox WHERE username = '%u'
user_query = SELECT maildir, 89 AS uid, 89 AS gid FROM mailbox WHERE username = '%u'

Cyrus-SASL
Khusus untuk keperluan autentikasi (memeriksa apakah user yang login via Dovecot atau POSTFIX adalah user yang valid) digunakan program Cyrus-SASL.
instalasi modul yang diperlukan untuk Cyrus-SASL adalah:
yum install cyrus-sasl cyrus-sasl-mysql cyrus-sasl-plain pam_mysql

pastikan /etc/sasl2/smtpd.conf seperti berikut:
pwcheck_method: saslauthd
mech_list: plain login

set konfigurasi /etc/pam.d/smtp
auth required pam_mysql.so user=postfix passwd=mypassword host=localhost db=postfix table=mailbox usercolumn=username passwdcolumn=password
account sufficient pam_mysql.so user=postfix passwd=mypassword host=localhost db=postfix table=mailbox usercolumn=username passwdcolumn=password

untuk keperluan Virtual Domain, pastikan Cyrus memeriksa realm pada saat memeriksa user. Hal ini ditentukan oleh 2 file konfigurasi:
/etc/init.d/saslauthd pastikan memiliki baris:
PARAMS="${PARAMS} -a ${MECHANISMS} -r"

/etc/sysconfig/saslauthd pastikan menambahkan “-r” pada FLAG
SOCKETDIR=/var/run/saslauthd
MECH=pam
FLAGS=-r

Coba restart MySQL, POSTFIX, Dovecot, dan Cyrus-SASL. … And see what happen! 🙂

Saya belum bisa menuliskan step by step yang lengkap untuk proses setting ini. Tapi, mungkin Anda coba merujuk ke beberapa link berikut ini.
Virtual Users And Domains With Postfix, Courier, MySQL And SquirrelMail
Virtual Users And Domains With Postfix, Courier, MySQL And SquirrelMail (page-2)
Authentifikasi SMTP, POSTFIX & SASL
POSTFIX SMTP Authentication Dovecot SASL
SETTING UP EMAIL: A POSTFIX/DOVECOT HOWTO
SMTP Authentication Email Client
POSTFIX Configuration Paramaters
Postfix SASL Howto

Semoga bisa membantu.
Sorry for the incomplete installation notes. 🙂
Cuma sebagai pengingat pribadi saja.

Debug Query di MySQL

Berhari-hari memiliki masalah dalam instalasi Postfix untuk Multiple Domain, menggunakan MySQL untuk penyimpanan data. Entah mengapa, proses authentikasi smptd-nya selalu gagal. Karena data user & password tersimpan di MySQL, salah satu caranya adalah dengan trace setiap query yang di eksekusi oleh MySQL.

Debuggid di MySQL diaktifkan lewat file /etc/my.cnf

[mysqld]
log-output=FILE
general-log=1
general-log-file=/var/log/mysqlquery.log #pastikan file writetable

/var/log/mysqlquery.log harus dibuat manual.

# cd /var/log
# echo > mysqlquery.log
# chown mysql:mysql mysqlquery.log
# chmod 644 mysqlquery.log

Setelah itu, restart MySQL Anda.

Kini Anda bisa memeriksa setiap query yang di eksekusi oleh MySQL.
File log ini bisa berukuran sangat besar. Jadi, jangan lupa untuk menonaktifkannya (dengan cara memberi # atau menghapus konfigurasi tadi dibuat di my.cnf) jika Anda sudah tidak memerlukannya lagi.

Daftar Profile Setting Operator

Berikut adalah daftar APN, Username, Password untuk profile setting yang digunakan untuk konektivitas modem/HP menggunakan jaringan GPRS 3G.
Semoga bisa membantu.

OPERATOR APN USERNAME PASSWORD
Telkomsel Prabayar flash (kosong) (kosong)
Telkomsel Unlimited internet (kosong) (kosong)
IM3/Mentari (time based) indosatgprs indosat@durasi indosat@durasi
IM3/Mentari (volume based) indosatgprs indosat indosat
Matrix Broadband indosat3g indosat indosat
IM2 indosatm2 (sesuai yang terdaftar) (sesuai dengan yang terdaftar)
XL http://www.xlgprs.net xlgprs proxl
Axis axis axis 123456
Three (3) 3gprs 3gprs 3gprs

WordPress 404 Server Error – Blank Comment (SOLVED)

Untuk blog di pujangga.net, saya menggunakan program wordpress.

Para pengguna wordpress selalu mendapatkan notifikasi email saat seseorang meninggalkan komentar di blog Anda. Beberapa waktu belakangan, saya selalu menerima notifikasi komentar masuk, tapi ia berupa komentar kosong. Selama ini saya menganggap itu spam, tapi setelah diperhatikan, “kok jarang ada lagi yang komen ya di blog”.

Selidik punya selidik, ternyata memang para pengguna yang menggunakan browser Internet Exporer (IE) selalu menemui pesan 404 Server Error saat mereka hendak meninggalkan komentar.

Beberapa hari coba otak-atik, belakangan diketahui, salah satu penyebabnya adalah Pretty Permalinks di WordPress. Sebab, jika diubah ke Ugly Permalinks, semua berjalan normal. Tapi mengingat banyak link yang menggunakan alamat dengan format Pretty Permalinks, perubahan itu akan membuat banyak sekali broken links. Jadi, coba berusaha mencari solusi untuk masalah ini.

Debugging file PHP wordpress, berhari-hari, hasilnya nihil. Try to think out of the box, dan … akhirnya ketemu. It’s the Akismet Plug-in. Pas Akismet di-deactivate, kini meninggalkan komen lewat IE bisa berjalan lagi.

Jadi, sampai saat ini, Akismet saya berada dalam keadaan non-aktif. Nanti di ulik lagi lah. Klo ngga, makin banyak komen yang terlewatkan dari para pengunjung blog.

Koneksi GPRS Modem di Linux UBUNTU 9.04

Koneksi Modem GPRS di Linux ternyata tidak ribet yang dikita. PLUG ‘N PLAY! Tinggal, colok (USB), yang langsung kebaca beserta account koneksinya.

Berikut ini adalah contoh koneksi Sony Ericsson K810i ke Ubuntu 9.04 (sebagai modem GPRS) di COMPAQ Presario V3000.


Begitu colok, langsung muncul dialog box diatas. Next!


Pilih operator yang digunakan. Pilihan diatas mungkin berbeda untuk setiap perangkat. Perangkat yang saya gunakan adalah HP Sony Ericsson K810i.


Klik Apply.

Untuk koneksi, klik Network Applet yang berada disebelah kanan atas desktop, jika semuanya berjalan dengan baik, pada menu akan muncul juga nama account operator terkait. Klik pada nama account tersebut maka … voila! You are connected! 🙂

Hah, makin cinta deh ama Jaunty Jackalope. 🙂

Uang Pecahan Rp. 2000

Hari ini (9 Juli 2009), Bank Indonesia resmi mengeluarkan pecahan uang baru senilai Rp. 2000.

Uang pecahan baru tersebut bergambar Pangeran Antasari (Pahlawan Nasional asal Banjarmasin, Kalimantan Selatan) dengan gambar bagian belakang Tarian Adat Dayak. Uang tersebut akan berlaku sebagai alat pembayaran yang sah mulai tanggal 10 Juli 2009. Pemilihan gambar pada uang tersebut mengacu kepada desain uang kertas sebelumnya yang bertemakan Pahlawan Nasional. Hal ini sebagai bentuk apresiasi kepada para pahlawan dan untuk turut serta melestarikan budaya bangsa.

Uang kertas baru pecahan Rp2.000 berwarna dominan abu-abu dengan unsur pengaman berupa tanda air bergambar Pangeran Antasari dengan benang pengaman yang tertanam di kertas uang dan bertuliskan BI2000 berulang-ulang yang akan memendar merah di bawah sinar ultraviolet. Uang kertas pecahan baru ini juga mengakomodasi kebutuhan para tuna netra dengan menyediakan kode tertentu (blind code) di samping kanan bagian muka uang yaitu berupa kotak persegi panjang yang dicetak secara intaglio.

Pecahan 2000 rupiah

Pecahan 2000 rupiah

sumber asal duratia.net

Masalah baru buat para programmer
Programmer pasti tau program untuk menghitung uang kembalian. Salah satu hal yang kadang bikin ribet adalah pecahan uang Rp. 20.000. Nah sekarang, ada pecahan Rp. 2.000. Program untuk menghitung uang kembalian pasti tambah panjang. 😀