Personal Finance: The software that I use

I’ve talked about the personal finance wisdom I’ve picked up so far and as I’ve said, you can’t improve things you don’t keep track of.

“But keeping track of finances is hard!” you say.

Yes, indeed; but with the help of software (or four), I’ve managed to keep track of all of my expenses for the past year without fail.

1) Good ole’ Spreadsheet
Nothing beats the good ole’ spreadsheet. I use this to keep track of my credit card. I’ve devised of a system on how I pay for my credit card in a way that allows me to pay for certain items in particular. This means, the amount I pay to my credit card is exactly the cost of one (or more) items. When I pay my credit card Php 2,433.45, it was for 6 different things I’ve bought 3 months ago. This way, I avoid the anxiety of not knowing what I’m paying for, and this helps me keep track what exactly I’m using my credit card on.

2) Toshl
This is, by far, the easiest software I’ve used on mobile. It really helps me record my expenses the moment I make them or shortly right after. I’m on Pro, as I need the multiple incomes, but the free tier is plenty useful by itself.

3) Splitwise
If Toshl helps me keep track of my expenses, Splitwise helps me keep track of personal debt. I know who owes me and exactly how much. I also know who I owe and exactly how much.

It’s made our – me and my roommates – lives easier. Someone’s paid the electricity? Record it in Splitwise. Someone’s bought groceries? Splitwise. When someone sees their debt ballooning, they pay in cash and record it in Splitwise.

I also use this to keep track of reimbursements, along with a spreadsheet.

This was a new addition. Recently, my expenses now closely track my income which means I don’t get to save as I did before. On top of that, my savings has been wiped out because of an emergency. So, I needed to budget and budget well. But more than the software, what’s more useful is YNAB’s methodology. The methodology takes some time getting used to as it’s an entirely different mindset on how to approach budgeting. Good thing that the software makes applying the methodology really easy. The full price is pretty steep though (USD 60), but it’s an investment.

YNAB is pretty redundant with Toshl, but I like the ease of use of Toshl so I’m keeping both. I just consolidate Toshl’s entries at the end of the day and record it on YNAB in consolidated categories.

That’s about it. I’ll talk about my workflow and how I manage this mess of numbers in the next post.

7 Personal finance wisdom from a 20-something

Ha! Bait title!

Here are some sound personal finance wisdom I’ve picked up along the way, in no particular order.

1) Don’t fly a ship you can’t afford to replace.
From Eve Online (aka Spreadsheets in space) and is probably the first thing older players will tell new players. Basically, if you can’t afford to buy two of the thing, don’t buy one in the first place. It’s a good rule to live by, which is precisely why it’s hard to live by.

2) An asset is something that puts money in your pocket. A liability is something that takes money out of your pocket.
From Rich Dad, Poor Dad by Robert Kiyosaki. If there’s anything in the book you should take away, this is it. It is an oversimplification but it should be enough for quick assessments when you’re not sure if a thing is an asset or a liability. If an “investment” doesn’t pass this acid test, then it’s most likely a liability, no matter how persuasive the salesperson in front of you is.

3) Only budget money you currently have.
Rule number 1 of YNAB. (I’m currently on the free trial, hoping for a discount in the next 7 days.) You only get to spend money that you do have. No matter how it feels, credit card is not free money.

4) You can’t improve things you don’t keep track of.
Mostly related to weight loss and exercise, but totally applicable in personal finance. How can you budget properly if you don’t know where you’re spending your money?

5) Income – Savings = Expenses
As opposed to Income = Expenses + Savings. This highlights that you should set aside for savings first, before spending the rest of your money.

6) Cheap, Fast, Easy/Good: Pick 2.
This is true for software projects and this is true just about anywhere. Realize that people will be willing to pay if you can either save them time or save them effort.

7) Opportunity cost and sunk cost
I’ve written about opportunity cost. Sunk cost goes like this: I gave you Php 100 and you spent Php 20. Any future spending decision should be made as if I just gave you Php 80. The Php 20 you spent is now irrelevant. Sunk cost is interesting because keeping this concept in mind helps remove emotions from any financial decision.

These are principles I’ve put into place, mentally, such that when I have to make a financial decision, I only need to consult these principles and see if spending on something is compatible with my internal spending principles. There are loopholes in there if you look close enough, but for most of the time, these will suffice.

Up next, I’ll write about the tools that I use to keep track of my finances.

Freedom within boundaries

I eat whatever I want, as long as it fits my calorie and nutrient goals.
I can spend on things I like, as long as it fits my budget.
I can do whatever I want, as long as I do things that I should.

It’s a bit counterintuitive with the common definition of freedom, but it is pretty freeing.

Legend of Mana: A story about love

Legend of Mana just popped into my head lately. I re-read the storyline again [1] and I was like “Holy sh*t, this game had a really cool storyline.”

It was about love, and all its beauty and nastiness. It was a pretty mature take on a topic as cliched as they come. I sort of got to relate to it back then, but I was too immature to really appreciate the message.

In retrospect, it was easy enough to lose the storyline as you get involved in the minutiae of killing monsters, picking up exp/gold/items and solving puzzles. The grind to this game was really endless.

Gameplay-wise, it was pretty unique. The battle system was kind of like a side-scrolling beat ’em up. It was also the first time I encountered farming, pet making/raising, and item crafting in just one game. I haven’t seen anything quite like it in recent times.

I’ll probably get around to buying a PS3 within this year because of this.



Simply put, and fairly obvious given the introduction speech, this game is about love. More specifically, its about both the positive and negative effects of love, and if it is worth the struggle to bring love back in to the world.

This is first hinted at in the introduction with the story of the Mana Tree burning down and mankind growing afraid of love. The purpose of the game is then given with the line “I am love! Find me, and walk beside me.” Thus you begin your quest to bring love back into the world.

Now, rather than just bring love back in, the Mana Goddess apparently decides that you need to see all sides of love, good and bad, before you can make the decision to bring it back. This is the purpose of the three major story arcs that you must complete- each one is an example of the dangers of one specific type of love. Listed below are the three arcs and the aspect of love they best represent.

The Fairy Arc- Romantic Love
The main focus of this arc is the romantic relationship between Matilda and Irwin, and the resulting havoc it wreaks on the world. Nearly all of Irwin’s destructive actions are based on his relationship with Matilda, from stealing her power to Matilda refusing to stop him because she loves him and respects his decision, even if it means the end of the world. Irwin sums it up nicely at the end when he says he needs to be freed “from a spell named Matilda”.

The Dragon Arc- Familial Love
In contrast, the conflict in this story arc arises from Larc desiring to be reunited with his sister, Sierra. The sole purpose of him helping to bring Draconis back into power is so that he can once again walk the mortal world, even if it means threatening the world with destruction. Finally, at the conclusion of the quest line, he decides to suffer through his punishment, even if it greatly delays his reunion with his sister.

The Jumi Arc- Communal Love
The Jumi arc is probably the most complicated, but best implemented, symbol of the harmful effects of love. Prior to the beginning of this quest, Florina had been sacrificing her own life for the benefit of her people. Had this continued, there would have been no conflict. However, Sandra, who had a close relationship with Florina, grew to hate the Jumi for sacrificing someone she loved for their own survival, and kidnapped her. Enter the hero, who, after the quest is completed, sacrifices his/her own life out of love for the survival of the Jumi. The consequences of this sacrifice are brought home to the audience when they see Bud and Lisa’s response to the hero’s supposed demise.

Other than these three arcs, this theme is referred throughout the game by many different characters *cough*POKHIEL*cough*. Once the character witnesses one of these arcs, the path to the final test opens.

The final battle of the game is merely a symbol of the character deciding that Fa’Diel is once again ready to welcome love to the world, despite the darkness that it brings. The character’s fight with the Mana Goddess’s “dark half” shows that life is once again ready to embrace love. I think the Mana Goddess’s final speech is the best way to conclude this, so I’ll leave it in more capable hands :-D

I am the light. I am the darkness. Half of myself is what you have fought in the past. I create, I destroy, and I create again. I am love. Not all of me is just. Not all of me is pure. That is only half of myself. Those who desire my other half cross their swords. People’s freedom is lost, and my truth is buried. I shall show you my darkness. You must defeat me. You will become a hero. Open the path to those who search for me.

Standing on escalators

In Ayala, there’s this escalator that always pisses me off.
Not so much because it’s a one-lane escalator (in Ayala!), but because inevitably
there’s going to be someone who’ll stop walking and thus forcing everyone
to just stand there and wait.

“Maybe, she’s just tired.”
“Maybe, his legs hurt.”
“Maybe, she’s having girly pains.”

Oh the thoughts that I force myself to think to calm myself down.

Then the slow ride is over and I’m calmed down.

Good thing that the next platform has twin, dual lane escalators.
Then somebody stands in the left lane of the “fast lane” elevator.



It’s 2014.

This year will be a year of building up habits.
Building up the ones that I’d like to have.
My goal, at the end of the year, is to have these habits built up:

  • Workout
  • Sleeping/Work
  • Hygiene

Just 3 things.

I’ve managed to find a workout routine to stick to.
It’s simple and easy to follow and it’s beginner-friendly. I hope to follow through with this until my membership expires on April and by then, should have a good enough habit base that getting a continuing membership is a no-brainer. I’m happy to teach anyone who’s interested in the program. :)

Diet is still a tricky thing for me. I’m getting back into recording my meals in My Fitness Pal.

Sleeping/Work habits is just different sides of the same coin. Right now, I wake up at around 10 to 11 AM. I’m only able to work by 2pm and I stop at around 6pm until 12 midnight, where I go to the gym between 10PM and 12MN. From there, I try to get into the flow again until I become sleepy, which is around 2 to 3AM. Oftentimes, I’m left with the feeling that nearly my whole day went out the window.

I want to change that habit to something like: Wake up at 5AM, work until 8AM, have breakfast, work on non-coding stuff between 9AM until lunch, 1PM to 4PM should be coding work again and the rest of the day will be spent on dinner, gym and leisure. Not married to the actual times, but it’s more of being awake more in the day and spend more of the evening actually sleeping. I actually like being up early in the mornings. I just don’t like getting up.

I also want to incorporate daily reviews to what I’ve accomplished in the day and what I need to do the following day.

I’ve got my hygiene regiment down, I just have trouble sticking to it every time.

Okay, I’m sleepy!

Have a happy new year everyone!

Making Squid a transparent proxy

..has absolutely nothing (almost) to do with Squid.

It’s a single firewall rule like so:

-A PREROUTING -p tcp -m tcp -i wdev0ap0 --dport 80 -j DNAT --to-destination

That’s an IPTables rule, normally but Arch (at least the version I was working with) was using UFW so that goes inside my before.rules in /etc/ufw/before.rules, right at the top.

-A PREROUTING -p tcp -m tcp -i wdev0ap0 --dport 80 -j DNAT --to-destination

Make sure to restart ufw.

ufw disable && ufw enable

From Squid side, you just have to make sure that Squid is listening to a port transparently.
http_port 3128
http_port 3128 intercept.

That should do it.


I wanted to use a FQDN for the splash page though, so we used DNSMasq for DNS.
pacman -S dnsmasq

Then we just edit the /etc/hosts file and put in the FQDN that we want to map to the local IP (not localhost). Of course, this only ever works if your device has a static IP (which it should).

# /etc/hosts: static lookup table for host names

# localhost.localdomain localhost
::1 localhost.localdomain localhost

# End of file

In order for you to use the DNS on the device, you have to make it your first/default DNS. So, configure that on your network settings.

From here, I can change the Squid splash page config accordingly based on where my allow access page is.

Next steps:

  • Pass along default DNS setting during DHCP
  • Start squid and dnsmasq on startup
  • Remove Node.js apps from startup
  • Install Nginx
  • Map default Squid error page from the static HTML error to default web server on localhost (might not be needed)
  • Dealing with SSL on a transparent proxy setting
  • Changing upstream from eth0 to usb dongle

Thanks to Madumlao for all the help. :)

Squid Splash Page Notes

I’m playing with Squid and setting it up as a captive portal.
This is my notes on their documentation.

  • Top-down processing of rules gave me 90% of the troubles I encountered.
  • The deny_info path doesn’t really work. It should be a filename relative to the error_directory directory.
  • You have to manually create the session db/session folder the first time. mkdir /var/lib/squid/session && chmod 777 /var/lib/squid/session
  • To clear sessions from the server (for testing), you can delete and re-create the sessions folder: rm /var/lib/squid/session -r && mkdir /var/lib/squid/session -r && chmod 777 /var/lib/squid/session
  • Always check permissions.

Next things to do:

  • Making it a transparent proxy
  • Dealing with SSL (port 443)
  • Changing upstream providers from LAN to USB Dongle

Here’s a copy of my squid.conf:

# Recommended minimum configuration:

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src # RFC1918 possible internal network
acl localnet src # RFC1918 possible internal network
acl localnet src # RFC1918 possible internal network
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http

# Recommended minimum Access Permission configuration:
# Deny requests to certain unsafe ports
http_access deny !Safe_ports

# Deny CONNECT to other than secure SSL ports
http_access deny CONNECT !SSL_ports

# Only allow cachemgr access from localhost
http_access allow localhost manager
http_access deny manager

# We strongly recommend the following be uncommented to protect innocent
# web applications running on the proxy server who think the only
# one who can access services on “localhost” is a local user
#http_access deny to_localhost


# Squid normally listens to port 3128
# http_port 3128 transparent
# http_port 80 vhost
# http_port 3128 intercept
http_port 3128 intercept

error_directory /makubex

#### Passive ####

# external_acl_type splash_page ttl=60 concurrency=100 %SRC /usr/lib/squid/ext_session_acl -t 7200 -b /var/lib/squid/session.db
# acl existing_users external splash_page
# http_access deny !existing_users
# deny_info 511:splash.html existing_users

#### Active ####

# external_acl_type session ttl=300 negative_ttl=0 children-startup=1 concurrency=200 %LOGIN /usr/lib/squid/ext_session_acl
# acl session_login external session LOGIN
# http_access deny !session
# deny_info session

external_acl_type session concurrency=100 ttl=3 %SRC /usr/lib/squid/ext_session_acl -a -T 10800 -b /var/lib/squid/session/
acl session_login external session LOGIN
external_acl_type session_active_def concurrency=100 ttl=3 %SRC /usr/lib/squid/ext_session_acl -a -T 10800 -b /var/lib/squid/session/
acl session_is_active external session_active_def
# acl clicked_login_url url_regex -i$
acl clicked_login_url url_regex -i$
http_access allow clicked_login_url session_login
http_access deny !session_is_active
deny_info 511:index.html session_is_active
# deny_info session_is_active
# acl clicked_login_url url_regex -i$

##### Catch All #####

# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
http_access allow localnet
http_access allow localhost

# And finally deny all other access to this proxy
http_access deny all

# Uncomment and adjust the following to add a disk cache directory.
#cache_dir ufs /var/cache/squid 256 16 256

# Leave coredumps in the first cache dir
coredump_dir /var/cache/squid

# Add any of your own refresh_pattern entries above these.
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320

visible_hostname makubex

Using Dropbox Chooser within ActiveAdmin

We use Dropbox quite heavily in Loudcloud. I’m working on an internal CRM system and since all of our files are on Dropbox anyway, I figured it would be super helpful to just have to link to our Dropbox files.

Here are the relevant files:

# app/inputs/dropbox_input.rb
class DropboxInput < Formtastic::Inputs::FileInput
  def to_html
    input_wrapping do
      label_html <<
      builder.text_field(method, input_html_options.merge({ type: "dropbox-chooser", style: "visibility: hidden;" }))

# app/admin/invoice.rb
ActiveAdmin.register Invoice do
  form do |f|
    within @head do
      script src: "", id: "dropboxjs", type: "text/javascript", "data-app-key" => "APP_KEY_HERE"

    # ....

    f.inputs "Official Receipt" do
      f.input :or_file_url, as: :dropbox, label: "OR File URL"

    # ....


Nested forms with polymorphic association in Active Admin/Formtastic

I spent nearly the whole day making this work.

Given models:
Invoice, has_many :items
Item belongs_to :itemizable, polymorphic: true
Domain & Service has_many :items, as: :itemizable

The problem was multiple things:

  1. The automagic of Formtastic can’t detect the collection if it’s a polymorphic association
  2. Formtastic doesn’t really play well with non-existent attributes

Initially, I’ve thought of just doing:

ActiveAdmin.register Invoice do
  form do |f|    
    # ...
    f.has_many :items do |item|
      item.input :itemizable, collection: (Domain.all + Service.all)
      item.input :quantity
      item.input :price_per_piece


But this fails because 1) domains and service can share the same id and 2) I have no way to tell what the item was.
A few hours in and I was going nowhere. It’s surprisingly hard to look for anything related to polymorphic associations on Formtastic. This post gave me an idea however.

So, I’ve thought, why not just hold the id temporarily on an accessor attribute and just do the assignment from a callback before validation kicks in based on which attribute it went into? Raise an error if both were filled up.

It worked! I can now save new polymorphic records. (look at Item#assign_itemizable)

There’s a small problem however. The form to edit an existing record doesn’t pre-populate the corresponding select dropdowns. The solutions was rather simple, override the reader method to return the id of the itemizable if the itemizable is a member of the class.

Maintenance-wise, everything here would add overhead for every new itemizable model I would associate to item, but overall, I think it was a pretty elegant hack. *pats self at back*

Here’s the complete code:

# app/models/invoice.rb
class Invoice < ActiveRecord::Base 
  has_many :items

  accepts_nested_attributes_for :items

# app/models/item.rb
class Item < ActiveRecord::Base
  before_validation :assign_itemizable

  belongs_to :invoice
  belongs_to :itemizable, polymorphic: true
  validates :itemizable, presence: true

  attr_accessor :itemizable_domain, :itemizable_service

  def itemizable_domain if self.itemizable.is_a? Domain

  def itemizable_service if self.itemizable.is_a? Service

  def assign_itemizable
    if [email protected]_domain.blank? && [email protected]_service.blank?
      errors.add(:itemizable, "can't have both a domain and a service") 

    unless @itemizable_domain.blank?
      self.itemizable = Domain.find(@itemizable_domain)

    unless @itemizable_service.blank?
      self.itemizable = Service.find(@itemizable_service)

# app/admin/invoice.rb
ActiveAdmin.register Invoice do
  form do |f|
    f.inputs "Invoice" do 
      f.input :customer
      f.input :invoice_number
      f.input :issuing_person
      f.input :issued_on
      f.input :remarks
    f.has_many :items do |item|
      item.input :itemizable_domain, collection: Domain.all
      item.input :itemizable_service, collection: Service.all
      item.input :quantity
      item.input :price_per_piece


Edit: Fixed a bug in Item because I overwrote the accessors, which were being called in the validation. This caused a sort of chicken-egg situation, and ultimately causes the validation to fail all the time. Changed .empty? to .blank? so it doesn't barf out on nils.