<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Brady&#039;s Blog</title>
	<atom:link href="https://uberbrady.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://uberbrady.com</link>
	<description>My Blog</description>
	<lastBuildDate>Wed, 18 Dec 2024 13:03:29 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>How to solve all marital problems</title>
		<link>https://uberbrady.com/2024/12/how-to-solve-all-marital-problems/</link>
					<comments>https://uberbrady.com/2024/12/how-to-solve-all-marital-problems/#respond</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Wed, 18 Dec 2024 12:43:29 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://uberbrady.com/?p=274</guid>

					<description><![CDATA[One of the challenges we run into when we are married is &#8220;where are we going to eat?&#8221; or &#8220;What are we doing tonight?&#8221; It&#8217;s really easy when one person or the other says &#8220;I really want &#60;x&#62;!&#8221; Or &#8220;I really do not want to do &#60;y&#62;.&#8221; That&#8217;s no big deal. But, in real life, &#8230; <a href="https://uberbrady.com/2024/12/how-to-solve-all-marital-problems/" class="more-link">Continue reading<span class="screen-reader-text"> "How to solve all marital problems"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">One of the challenges we run into when we are married is &#8220;where are we going to eat?&#8221; or &#8220;What are we doing tonight?&#8221;</p>



<p class="wp-block-paragraph">It&#8217;s really <em>easy</em> when one person or the other says &#8220;I really want &lt;x&gt;!&#8221; Or &#8220;I really do not want to do &lt;y&gt;.&#8221; That&#8217;s no big deal.</p>



<p class="wp-block-paragraph">But, in real life, those things aren&#8217;t that common. There&#8217;s often this, kind-of, &#8216;meh&#8217; reaction, a lot of the time. &#8220;Where do you want to eat?&#8221; &#8220;I dunno, where do <strong>you</strong> want to eat?&#8221; And that goes back and forth and you never get anywhere.</p>



<p class="wp-block-paragraph">I started to find myself trying to <em>guess</em> what Alison wanted, and suggesting that. And she would try and guess what <em>I </em> wanted, and suggest that.</p>



<p class="wp-block-paragraph">It ends up in a cycle, and it sounds a lot like the old saying about &#8220;Being married is just asking each other, &#8216;I dunno, what do you want to eat?&#8217; over and over until you die.&#8221;</p>



<p class="wp-block-paragraph">But we are big giant nerds who like to solve problems. So we&#8217;ve come up with a system. A system which I am now going to share with you, to fix all sources of martial strife.</p>



<h2 class="wp-block-heading">The System</h2>



<p class="wp-block-paragraph">This mostly works with Boolean options &#8211; true/false, yes/no, go/stay, etc.</p>



<p class="wp-block-paragraph">You come up with your &#8216;number&#8217; &#8211; on a scale of 0-100, how much do you want the option that you want?</p>



<p class="wp-block-paragraph">And the other person comes up with <em>their</em> number. And you compare. Whoever&#8217;s number is a larger absolute value from 50, their option wins. You take your W&#8217;s and your L&#8217;s, and the system just <em>works.</em></p>



<p class="wp-block-paragraph">I asked Alison if she wanted to go to the mall today. Me, personally, I could&#8217;ve gone or not gone &#8211; my number genuinely felt like a 50 (coin toss). She reports she&#8217;s at a 60 for no-go. Boom. Done. We don&#8217;t go to the mall.</p>



<p class="wp-block-paragraph">What&#8217;s great about this is there&#8217;s no guilt. The system just works as designed. When you win, don&#8217;t back down from your win, just take it. When you lose, accept your L &#8211; the other person&#8217;s desire is stronger than yours, it needs to be respected.</p>



<p class="wp-block-paragraph">There are always going to be some things like &#8220;never&#8221; or &#8220;always&#8221; &#8211; and that&#8217;s more out-of-scope from this. If you absolutely do <strong>not</strong> want to go to the mall today, then put your foot down and don&#8217;t go.</p>



<p class="wp-block-paragraph">But, again, those are easy. It&#8217;s that &#8220;meh&#8221; line that&#8217;s harder to walk.</p>



<p class="wp-block-paragraph">One thing that <em>hasn&#8217;t</em> come up since we started to use this is dealing with very high absolute values. Someone being at 90 versus someone being at 5. That&#8217;s going to be a lot harder to navigate, and losing after tossing out a 90 is going to really sting.</p>



<p class="wp-block-paragraph">We haven&#8217;t yet had to make our votes &#8216;secret&#8217; &#8211; for fear that someone might inflate or deflate their number to try to &#8220;just get along&#8221; or &#8220;go with the flow.&#8221; Or to &#8220;get your way.&#8221; But if we start to see that, we&#8217;ll probably do something where we write our number down in the Notes app on our phones or something. But that hasn&#8217;t happened yet.</p>



<p class="wp-block-paragraph">Honestly, when I <em>do</em> &#8216;lose&#8217; with this system I actually feel pretty good about it &#8211; if I&#8217;m 52% for something and she&#8217;s 44%, her feeling is stronger (2 points above 50, versus 6 points down from 50) &#8211; so long as I was honest at my 52, I&#8217;m definitely going to feel good that her choice was right for her and I can do it.</p>



<p class="wp-block-paragraph">So far, for us, it hasn&#8217;t failed yet. The only time we&#8217;ve had problems with this was one time where we didn&#8217;t use it &#8211; I wanted to go to this &#8220;meet up&#8221; event here and she <em>really</em> didn&#8217;t. We should&#8217;ve put numbers on that and either she would&#8217;ve gotten dragged to the event, or I could&#8217;ve felt better about not going, knowing that she felt more strongly than I did.</p>



<p class="wp-block-paragraph">So, you&#8217;re welcome. Enjoy a life of strife-free marriage.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2024/12/how-to-solve-all-marital-problems/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The Latest WordPress Psychopathy</title>
		<link>https://uberbrady.com/2024/10/the-latest-wordpress-psychopathy/</link>
					<comments>https://uberbrady.com/2024/10/the-latest-wordpress-psychopathy/#respond</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Sun, 13 Oct 2024 10:01:28 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://uberbrady.com/?p=269</guid>

					<description><![CDATA[Background on me: So, as you may or may not know, I work at an Open Source company. We distribute our software (Snipe-IT) for free &#8211; and we support it, as best we can, also for free. But you can also pay us to host it for you, and we will be happy to do &#8230; <a href="https://uberbrady.com/2024/10/the-latest-wordpress-psychopathy/" class="more-link">Continue reading<span class="screen-reader-text"> "The Latest WordPress Psychopathy"</span></a>]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Background on me:</h2>



<p class="wp-block-paragraph">So, as you may or may not know, I work at an <a href="https://grokability.com">Open Source company</a>. We distribute our software (Snipe-IT) for free &#8211; and we support it, as best we can, also for free. But you can also pay us to host it <em>for</em> you, and we will be happy to do that. Or if you need to run it on your own infrastructure, you can pay us for support. This has worked out great for us. We do have some users who leave our paid services saying &#8220;moving to self-hosted!&#8221; &#8211; which, hey, less money for us, so not necessarily great news. But we have many, many more who migrate from their self-hosted installs to ours.</p>



<p class="wp-block-paragraph">So open-source, for us, is not only an ethos that we believe in. But, just to be very, very clear &#8211; it absolutely <strong>is</strong> an ethos that we believe in. <strong>But</strong> it has a <em>side effect</em> of giving us a pool of potential customers &#8211; and they&#8217;re the best types of customers because they know the software already. And our hosted version, versus our &#8220;open source version&#8221; are both exactly the same.</p>



<p class="wp-block-paragraph">Yes, we have to spend more resources supporting free users on GitHub, and Discord, and wherever else we might find them. That&#8217;s true. But our users will also happily support each other, and we don&#8217;t have to do <strong>any</strong> marketing at all in order to get a steady flow of customers. So, IMHO, you could say that this is a &#8220;cost of doing business&#8221; or maybe a &#8220;loss-leader,&#8221; from a business perspective. (Though, again, just to reiterate &#8211; we do Open Source because our entire careers have been built on open source. The language we write in is open source. The database we use is open source. The Operating System we use is open source. So this &#8216;thing&#8217; that has given us so much, it makes sense for us to give back something. And, maybe, without open source I don&#8217;t know that we&#8217;d have jobs in tech at all?)</p>



<h2 class="wp-block-heading">Background on WordPress:</h2>



<p class="wp-block-paragraph">WordPress has been, like, our &#8220;Big Sibling&#8221; since we began. They have a very similar model to ours &#8211; you can download WP for free and run it right now. In fact, this very blog runs on it. Or you can pay them to host it for you.</p>



<p class="wp-block-paragraph">By doing that they&#8217;ve become a company that earns <strong>billions</strong>. Matt Mullenweg himself is reportedly worth somewhere in the neighborhood of $400 million dollars.</p>



<p class="wp-block-paragraph">We&#8217;ve wanted to be just like them &#8211; never took VC money, never took any kind of investment, just built a good business from the ground up and employed a bunch of people, and provided a great product for free, and also, optionally, a paid-for product.</p>



<p class="wp-block-paragraph">They got big enough that they <strong>do</strong> have competitors who sell the very same product that they sell. WPEngine being the pertinent example today.</p>



<p class="wp-block-paragraph">WPEngine has a different angle on how they do WordPress. They enable some stuff. They turn off other stuff. They charge for some things, they don&#8217;t charge for other things.</p>



<p class="wp-block-paragraph">And &#8211; and this is a bit of a dick move &#8211; they also don&#8217;t contribute much back to the open source community. The thing is, while I might call it a &#8220;dick move,&#8221; it&#8217;s also completely and totally permissible.</p>



<p class="wp-block-paragraph">And that should be the end of the story, right there. WordPress is making billions, they have a competitor who&#8217;s also making hundreds of millions or billions, and that competitor doesn&#8217;t do a good job of contributing things upstream. And all of that is fine and everyone should be happy. Or at least happy-ish.</p>



<h2 class="wp-block-heading">The state of affairs, as of a week or so ago</h2>



<p class="wp-block-paragraph">But Matt (the founder of WordPress) has fucking <strong>lost his fucking marbles.</strong> He changed the copyright on the &#8220;WP&#8221; and &#8220;WordPress&#8221; marks. All of a sudden. He&#8217;s blocked third-party access to updates and plug-ins for WordPress. He&#8217;s gone on tirades about WPEngine, his competitor. There are lawsuits and counter-suits flying around.</p>



<p class="wp-block-paragraph">This is an absolute violation of not only the spirit of open source, but very much so the <strong>letter</strong> of it. You can&#8217;t say &#8220;my software is open source until you make at least a million bucks a year on it, and then it isn&#8217;t.&#8221; That&#8217;s not how it works.</p>



<p class="wp-block-paragraph">Big names like DHH &#8211; a guy who I have taken as my personal goal to just &#8220;not be like&#8221; &#8211; has even come out swinging saying that WordPress is very, very much in the wrong here.</p>



<p class="wp-block-paragraph">So. Cool, cool. Whatever. People on the internet are going to do weird Internet things. I have this blog, our <a href="https://snipe.pt">https://snipe.pt</a> blog, and we have a corporate blog &#8211; and I bet that Alison has a few more blogs I&#8217;m not remembering, all hosted on WordPress. This &#8220;drama&#8221; (a misnomer IMHO) is a nuisance, and sad, but shouldn&#8217;t affect us.</p>



<p class="wp-block-paragraph">But it <strong>does</strong> and it <strong>will.</strong></p>



<p class="wp-block-paragraph">Because I&#8217;m <strong>sure</strong> that we&#8217;re going to have customers who start to ask, &#8220;how can I be sure you aren&#8217;t going to go full Matt on us?&#8221;</p>



<p class="wp-block-paragraph">And <strong>that&#8217;s</strong> a big fucking problem. It hasn&#8217;t happened yet, thank God, but it could very well happen. And I don&#8217;t know what I might tell someone if it did.</p>



<p class="wp-block-paragraph">So, even though this doesn&#8217;t directly affect us, it can possibly have an effect on us. So, now, we have to worry a little bit. No need to <em>do</em> anything, but, probably, have a little worry.</p>



<p class="wp-block-paragraph">This is where I was as of last night. A little worried, but not losing sleep or anything.</p>



<h2 class="wp-block-heading">The Latest</h2>



<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter"><div class="wp-block-embed__wrapper">
<blockquote class="twitter-tweet" data-width="550" data-dnt="true"><p lang="en" dir="ltr">We have been made aware that the Advanced Custom Fields plugin on the WordPress directory has been taken over by WordPress dot org.<br><br>A plugin under active development has never been unilaterally and forcibly taken away from its creator without consent in the 21 year history of… <a href="https://t.co/eV0qakURLc">pic.twitter.com/eV0qakURLc</a></p>&mdash; Advanced Custom Fields (@wp_acf) <a href="https://twitter.com/wp_acf/status/1845169499064107049?ref_src=twsrc%5Etfw">October 12, 2024</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div></figure>



<p class="wp-block-paragraph">While what most of WordPress has done has been generally awful, this is the first time they&#8217;re doing something that is actually <strong>EVIL</strong>.</p>



<p class="wp-block-paragraph">These custom fields folks made a nice plug-in for WordPress. They contributed it back to WP&#8217;s github, as a good open-source citizen should. And WP just <strong>stole</strong> it.</p>



<p class="wp-block-paragraph">Now, mind you &#8211; the folks who wrote this plug-in <strong>are</strong> WPEngine. I suspected as much because I can&#8217;t imagine them just arbitrarily grabbing some third-party&#8217;s code and running with it. Though, hey, maybe they can do that next? The genie&#8217;s out of the bottle now.</p>



<p class="wp-block-paragraph">This is the last straw, for me. I&#8217;m going to move this blog onto something else. Unfortunately, I <strong>hate</strong> everything else.</p>



<p class="wp-block-paragraph">This is probably some of the worst destruction of value I&#8217;ve seen since Elon took over Twitter. Tons of goodwill &#8211; poof &#8211; destroyed in just a few shitty blog posts.</p>



<p class="wp-block-paragraph">I&#8217;ll do my best to report back on whatever I happen to come up with for my new hosting platform. Honestly, this is more a <em>symbolic</em> move rather than a technological one &#8211; because I just simply <strong>cannot</strong> be a party to this type of shit-fuckery. Shit-fuckery that may even have echo effects on my actual <em>business</em>.</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2024/10/the-latest-wordpress-psychopathy/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why I’m moving to Portugal</title>
		<link>https://uberbrady.com/2023/03/why-im-moving-to-portugal/</link>
					<comments>https://uberbrady.com/2023/03/why-im-moving-to-portugal/#comments</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Mon, 20 Mar 2023 21:21:56 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://uberbrady.com/?p=255</guid>

					<description><![CDATA[Boa Tarde! So for those of you who are my friends, none of this is news &#8211; but Alison and I are moving to Portugal. We don’t know when, and the process is really unpleasant and long, but as soon as our visas come through, things are really going to get moving. I’d be pretty &#8230; <a href="https://uberbrady.com/2023/03/why-im-moving-to-portugal/" class="more-link">Continue reading<span class="screen-reader-text"> "Why I’m moving to Portugal"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Boa Tarde!</p>



<p class="wp-block-paragraph">So for those of you who are my friends, none of this is news &#8211; but Alison and I are moving to Portugal. We don’t know when, and the process is really unpleasant and long, but as soon as our visas come through, things are really going to get moving. I’d be pretty shocked if we didn’t make it over there this year (unless we get flat-out rejected, and then who knows how long re-application would take). But I thought I might at least explain more about the <em>why</em> rather than the <em>how</em> &#8211; there are plenty of explanations about &#8220;how&#8221; that are already out there.</p>



<p class="wp-block-paragraph">As to why &#8211; well, I&#8217;ll keep that brief. This country doesn&#8217;t feel like it once was, after 45 got in office &#8211; but also, it&#8217;s been feeling like that more and more with each Republican that ever got in office in my lifetime. And it&#8217;s not the former President that scares me so much &#8211; presidents come and go. It&#8217;s the people who vote for him. <em>Those</em> people actually really scare me, and make me not want to live here.</p>



<p class="wp-block-paragraph">So it’s time to go. I want a <em>functioning</em> Democracy (even though I won’t be able to vote in it for a while). I want someplace warm. I will need some levels of creature comforts, because I am a bougie bitch. I want the general politics to line up with at least some of mine. And the <em>culture</em> to line up a little bit with mine (not interested in super-racist, super-sexist, etc.) Language need not be English (and, for Alison, she wanted it to definitely <em>not</em> be English). And the number one country we came up with was Portugal. (For what it’s worth, New Zealand would probably be second on the list, though I don’t think they’d ever actually have us).</p>



<p class="wp-block-paragraph"><strong>Known Pros:</strong></p>



<ol class="wp-block-list">
<li>Functioning Parliamentary Democracy. The Socialist Party (PS) is pretty dominant, but they don’t always win. The <strong>do</strong> have a separate vote for President, but the President’s  powers are pretty limited. (The current President is from the PS, and the “Assembly of the Republic,” or ”Parliament,” currently has an absolute majority with the PS &#8211; without having to form coalitions. That can, and will, change).</li>



<li>Some of the warmest weather in Europe. Can get chilly, especially in the North, but not too much so.</li>



<li>Lovely people who will leave you alone if you don’t feel chatty, but can be warm, charming, funny and even a little sarcastic if you let them in (and they let you in). Once you find a Portuguese friend they will move heaven and Earth for you.</li>



<li>Delicious food, from all around the world.</li>



<li>Solid internet service and cell service (in cities &#8211; in some rural areas, you’ll see the ’number of bars’ drop down to 0).</li>



<li>The Lisbon subway was prompt, with modern trains and great signage.</li>



<li>The full-size trains themselves took a bit of getting used to, but were also <em>very</em> pleasant to take throughout the country (modulo the Alfa Pendular, which I will get to later).</li>



<li>SOCIALIZED FUCKING MEDICINE. And that existing means that <em>private</em> healthcare is much, much cheaper (current advice is: use socialized medicine for severe things, like organ transplants and cancer, use your private healthcare insurance for normal everyday things, but then switch back to the socialized system for prescriptions)</li>



<li>Drug Decriminalization. We’re not big drug users or anything, but what I like here is that it means that the cops are more focused on real, like, crime-things, and not stupid things like drugs.</li>



<li>Prostitution is legal, pimping is not. Same reason as before &#8211; we don’t partake, but I’d rather cops focusing on other things. And love the idea that it’s not only that ”pimping ain’t easy” but also ”pimping ain’t LEGAL.” (though it wasn’t in the song, either, so, well, I digress).</li>



<li>Trans people seem pretty well-accepted, gay folks seem pretty well-accepted</li>



<li>Abortion is legal (though there have been attempts to change this)</li>



<li>Gay Marriage is legal!!!!!</li>



<li>Later lifestyle &#8211; we’re night-owls already so that works really well for us. It’s not hard to get food at 10:30 or 11:00.</li>
</ol>



<p class="wp-block-paragraph"><strong>Known Cons</strong> (and these are all ’nits’ &#8211; livable little annoyances)</p>



<ol class="wp-block-list">
<li>Cripplingly horrific beauracracy, which is rather infamous. Apparently a lot of other European countries are similar, but theirs is really awful.</li>



<li>Some very old buildings, which means some poor insulation, for both sound as well as heat/cold.</li>



<li>Some things we’ve grown accustomed to we’re just not going to be able to get there. (No Ranch sauce! We’re San Diegans &#8211; how will we be able to cope??!?!)</li>



<li>Some things can be really antiquated &#8211; like, buying subway tickets in lisbon with a credit card you buy a big long number online and then when you get to the station you have to type it in. You have to pay cash sometimes &#8211; not as often as I feared, but more often than I’d want. (Since the pandemic, I’ve gotten into the habit of not taking out cash for months at a time).</li>



<li>The worst banking system I’ve seen. Nothing earns interest. You get nickle-and-dimed for everything. I’d do better to just keep my money under a mattress and would get a better return.</li>



<li>Some really nasty history &#8211; we are talking about the place that literally invented chattel slavery</li>



<li>There are gonna be shitty people there, just like there are shitty people here. We saw some graffiti saying ”COVID = NAZISMO = SOCIALISMO”, and we saw an ’anti-vax parade’.</li>
</ol>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="2934" height="487" src="https://uberbrady.com/wp-content/uploads/2023/03/IMG_2148-copy.jpg" alt="" class="wp-image-259"/></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"><strong>Unexpected Pros</strong></p>



<ol class="wp-block-list">
<li>In bigger cities, the ’MultiBanco’ system (when they offer it) allows contactless payments, right with your Apple Watch or Phone. It’s really quite nice. And if you <em>do</em> use a credit card, it never leaves your hand &#8211; they don’t take  it away then bring it back, you can just tap or insert it right there on the mobile terminal your server brings you.</li>



<li>Hooking up utilites and stuff &#8211; once you’ve got it going you just put in your IBAN number and it just takes the money out &#8211; easy-peasy.</li>



<li>They actually had a revolution to escape out of dictatorship. That’s pretty cool! (Yes, it’s embarassing that I didn’t know this. Blame American public schools)</li>



<li>And this is going to sound like a back-handed compliment, but it isn’t &#8211; European Portuguese is <em>hard</em>. But we very much do like a challenge <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>



<li>As our Portuguese gets a little better, we’re starting to understand more and more bits of other Romance languages &#8211; we were watching something in Romanian and both of us said, ”wait &#8211; why did I understand that?!” And something similar for French, and Italian. And the weird thing is that our Spanish is<em> still</em> better than our Portuguese (though not for long!). Basically some weird feature of Portuguese, I guess, that it’s closer to some of the ”Vulgar Latin” roots? I dunno, I read something on Wikipedia or something <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f61b.png" alt="😛" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>



<li>Because of the way Parliament works, you can get little teeny parties that have different platforms, and if coalition-building happens, maybe they can get some of their stuff pushed through. There’s the Pessoas-Animais-Natureza party (PAN &#8211; “People, Animals, Nature”) that’s won a seat or two. The PCP (Partido Comunista Português) also has had a seat here and there (and it’s WEIRD to see sickle-and-hammers around on campaign posters. And it’s <em>weirder</em> to read what they’re saying and say, ”hrm, those are actually some decent ideas&#8230;”)</li>



<li>Some really <em>amazing</em> laws that we don’t have here. I haven’t vetted all of these but they include:
<ol class="wp-block-list">
<li>You can’t take pictures of people without their permission</li>



<li>It’s illegal to discriminate in housing to people with pets (though our real estate person said that sometimes people still do)</li>



<li>Some strong privacy laws &#8211; I had to <em>redact</em> my social security number on my visa application because they <em>didn’t want to see it.</em> Same with some transaction details on my US-based bank.</li>



<li>Every public building (school, hospital, prison, etc) must have at least one vegan option.</li>



<li>AirBnB’s are regulated insanely hard &#8211; every (legal) one you see will have a completely identical plastic ”Alojamento Local” placard posted conspicuosly, and the licenses for those are hard to get.</li>
</ol>
</li>



<li>The anti-vax parade was orderly, and had cops embedded in it to prevent the parade-goers from getting attacked by the regular folks, and vice-versa.</li>



<li>They’re pretty smoking-friendly, but that’s actually kinda good for us &#8211; as we both vape and most places now treat them the same.</li>



<li>Green wine is actually delicious!</li>
</ol>



<p class="wp-block-paragraph"><strong>Unexpected Cons</strong> (that did genuinely suck, but, not deal-breakers)</p>



<ol class="wp-block-list">
<li>I went to get a haircut and shave and the douchey place I went to wouldn’t fix up Alison’s mohawk (I mean, just <em>shave the sides</em> is all!) because it wouldn’t ”Fit the aesthetic” they were going for. (I think they’re just sexist pieces of shit). Meh, that shit happens everywhere, but Portugal still isn’t some kind of Utopia.</li>



<li>The Alfa Pendular &#8211; a super-duper sophisticated train that uses ’tilting’ technology to be able to achieve very high speeds on relatively old tracks &#8211; can make you motion-sick. I got queasy, Alison got full-on horrifically sick.</li>



<li>My wife wants to live in the Algarve, and I’m more interested in Lisbon. SPOUSAL CONFLICT!</li>



<li>Driving is difficult, the streets are tiny, and weird little ’bollards’ will pop-up and prevent access to some areas.</li>



<li>Absolutely terrifying toilets. Honestly, Alison might start a blog about this once we get there.</li>
</ol>



<p class="wp-block-paragraph">So that’s why I want to move there. At this point, for me, it’s still more wanting to move <em>there</em>, rather than get away from <em>here</em>. Though the latter I must admit is true. I still can’t wait til we have us and our animals all safe in our apartment in Lisbon, wake up and walk the girls over near that one tree, then go out to the local cafe to have cafes pingados and some pasteis de nata, then relax for a bit with some portos, then wander around Lisbon for a bit until we go for a nice big lunch at noon, then it’s off to work!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2023/03/why-im-moving-to-portugal/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Creating a site-to-site VPN in AWS between regions</title>
		<link>https://uberbrady.com/2017/11/creating-a-site-to-site-vpn-in-aws-between-regions/</link>
					<comments>https://uberbrady.com/2017/11/creating-a-site-to-site-vpn-in-aws-between-regions/#comments</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Thu, 23 Nov 2017 03:42:22 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[networking]]></category>
		<guid isPermaLink="false">http://uberbrady.com/?p=225</guid>

					<description><![CDATA[I spent crazy amounts of hours &#8211; days, really &#8211; doing this. I figured I might at least try and save someone else some time. The solution I went with was a simple software-based VPN using AWS Linux instances in either region. I went with IPSec as my encryption/tunneling mechanism, and ISAKMP IKE as my &#8230; <a href="https://uberbrady.com/2017/11/creating-a-site-to-site-vpn-in-aws-between-regions/" class="more-link">Continue reading<span class="screen-reader-text"> "Creating a site-to-site VPN in AWS between regions"</span></a>]]></description>
										<content:encoded><![CDATA[<p>I spent crazy amounts of hours &#8211; days, really &#8211; doing this. I figured I might at least try and save someone else some time.</p>
<p>The solution I went with was a simple software-based VPN using AWS Linux instances in either region. I went with IPSec as my encryption/tunneling mechanism, and ISAKMP IKE as my method of sharing keys. I selected Libreswan as my VPN software. I evaluated and discarded several other potential solutions, but this is what I actually got to work for me.</p>
<p><span id="more-225"></span></p>
<h1>Prerequisites:</h1>
<ol>
<li>You need to know some intermediate networking. If you don&#8217;t, I don&#8217;t think I can help you.</li>
<li>You need to have non-overlapping network ranges in either region. If you don&#8217;t, you&#8217;ll need to evaluate some other kind of solution instead.</li>
<li>This isn&#8217;t a walkthrough; this is more of an explanation of my process, and I&#8217;m going to try and help give troubleshooting steps along the way.</li>
<li>You should probably be pretty good at AWS in general already. If not, you&#8217;re gonna have a bad time.</li>
</ol>
<h1>Instructions:</h1>
<h2>Stage 1: Information gathering</h2>
<p>You should have a &#8216;here&#8217; network, and a &#8216;there&#8217; network. Launch your instances. Allocate an EIP for either side (you wouldn&#8217;t want IP addresses to change). Spin up your boxes, and make sure they&#8217;re on public-facing subnets. Make sure you can ssh into them. Make sure they can speak ISAKMP IKE (UDP Port 500) to each other. Make sure they can speak IPSec NAT-T (UDP Port 4500) to each other.</p>
<p>Take note of the private network and netmask on the &#8216;here&#8217; side, and the private network and netmask on the &#8216;there&#8217; side. Take note of your EIP&#8217;s for either side too.</p>
<h2>Stage 2: ISAKMP IKE</h2>
<pre>yum install libreswan</pre>
<p>on both boxes. On either one, go to <code>/etc/ipsec.d</code></p>
<p>Create a file with the name of the <strong>other</strong> side of the network, with a <code>.conf</code> extension. Put this in there:</p>
<pre>conn name-of-connection-that-you-like
  left=my.internal.ip.address
  right=their.EXTERNAL.ip.address
  rightid=their.INTERNAL.ip.address
  leftsubnet=my_entire_private_subnet/CIDR-netmask (e.g. 1.2.3.4/20)
  rightsubnet=their_entire_private_subnet/CIDR-netmask
  authby=secret
  auto=start</pre>
<p>Do something similar (but not the same, as you can see) for the other side.</p>
<p>On both sides, create a file in that same directory with <code>name-of-connection-that-you-like.secrets</code> &lt;&#8212; yes, that&#8217;s plural. Contents should be:</p>
<pre>my.internal.ip.address their.internal.ip.address : PSK ""</pre>
<p><strong>In between the quotes put an extremely long random string, and make sure it matches on both sides of the network. </strong>Here&#8217;s an example way to get a nice long string for a PSK &#8211;</p>
<pre>dd if=/dev/random bs=1 count=33|base64</pre>
<p>The reason I don&#8217;t show it in there with the string already is I don&#8217;t want someone to copy-paste this and then have some stupid password already embedded.</p>
<p>On both sides, make sure to do:</p>
<pre>/sbin/chkconfig ipsec on</pre>
<p>Okay, now it&#8217;s time to see if we screwed something up. Don&#8217;t worry, you almost certainly did.</p>
<pre>service ipsec start</pre>
<p>(Do that on both sides). So, now we should try and see if we can at least have the tunnel up and running. Check out <code>/var/log/secure</code> to see if you see successful-looking things in there. It should say something about &#8216;connection established&#8217; or something like that. Do a ping from one of your VPN boxes to the <em>inside</em> IP address on the other box. The do the same from the other side. Don&#8217;t expect to be able to ping further into the network either way yet. We haven&#8217;t done that bit.</p>
<p>If you can ping across <strong>both ways</strong>, then you have gotten over the worst hump. The rest is much easier. You can skip to stage 2z. But if it still doesn&#8217;t work, read on.</p>
<h3>Stage 2a: Troubleshooting <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f641.png" alt="🙁" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<p>So your pings across didn&#8217;t work. That sucks, and being in that sucky state would probably be around 75% of the time I spent working on this solution. It&#8217;s hard, because you don&#8217;t have very good troubleshooting tools.</p>
<p>First off, <code>/var/log/secure</code> &#8211; this was the one that clued me in to the <code>rightid</code> setting that I settled on, above. I was getting messages saying &#8220;No configuration found for (other-sides-private-ip).&#8221; Maybe if you&#8217;re lucky, you&#8217;ll see something glaring in that log.</p>
<p>Any time you make changes to your config or your secrets file, be on the safe side and do <code>service ipsec restart</code></p>
<p>I tried a lot of <code>ipsec status</code> as well. That had a lot of gobbledygook, but sometimes gave me some decent clues.</p>
<p>Some other handy tools were <code>ip xfrm help</code> which was quite nice and led me to: <code>ip xfrm monitor</code> gives you a real-time-ish monitoring status of what the various IPSec things are doing.</p>
<p>And remember, all we should be able to do is ping from &#8216;here&#8217; to the <em>private</em> IP address of &#8216;there&#8217;. Nothing more (yet).</p>
<h3>Stage 2z: Your Future Self will thank you</h3>
<p>Okay, now comes a sneaky, but important part: reboot both ends. Once they&#8217;re back up, make sure you can ping across just as before.</p>
<p>I caught that I had forgotten my <code>chkconfig</code> on both sides by doing this. I also learned about the <code>auto=start</code> setting that I recommend above. It&#8217;s better to do this <strong>NOW</strong> rather than have someone call you up at 5am and have you scrambling to remember how you set up all this VPN stuff months and months ago.</p>
<h2>Stage 3: Routing</h2>
<p>Okay, you can ping from your gateway across your tunnel, but not any further. Let&#8217;s see if we can get some routing going to make your VPN actually useful.</p>
<h3>Stage 3a: One-and-a-half hops</h3>
<p>From the gateway on this side of the tunnel, we want to ping across the tunnel and to some device on their side of the network.</p>
<p>First, in the AWS Console, there is a setting in EC2 that you will need to change on the far side gateway instance. It&#8217;s called &#8220;Enable src/dest checks&#8221;. Disable those checks; they make sense for normal servers but they won&#8217;t work on a router.</p>
<p>Next, on your far-side instance, go into <code>/etc/sysctl.conf</code> and enable routing:</p>
<pre>net.ipv4.ip_forward = 1</pre>
<p>And also turn this weird setting off:</p>
<pre>net.ipv4.conf.default.rp_filter = 0</pre>
<p>I don&#8217;t know what that second one means, but something told me to turn it off (<code>ipsec verify</code> maybe?) so I did. Safest bet is to reboot the instance after that, but there&#8217;s also some way of reloading the <code>sysctl.conf</code> &#8211; I just don&#8217;t know what that is.</p>
<p>Next, let&#8217;s check that you have a reasonable security group set on your far-side gateway. It should already be allowing the various VPN protocols across &#8211; and that&#8217;s nice. But it <em>also</em> needs to have the ability to talk to whatever far-side instance you want to talk to. Test by ssh&#8217;ing into your far-side gateway, and do a <code>ping</code> or a <code>curl</code> or whatever to your far-side instance. It should work. If it does, your security group situation is probably OK.</p>
<p>Last couple of steps now. In the VPC settings in the AWS Console for the far-side region, add a route for the <em>near</em> network, via the far-side gateway. Repeat this for any different routing tables you might have (I have private and public routing tables, for example).</p>
<p>Now, ping across to the far instance. If that works, congrats! It took me a little fiddling &#8211; I had missed a security group, and I had missed one of my routing tables. But I eventually got there. Hopefully, you will too. There just aren&#8217;t as many moving parts to deal with here, luckily.</p>
<p>Things to keep in mind: if you can ping across the tunnel, and if your far-gateway can ping to your far-instance, then the issue almost <strong>has</strong> to be routing-related. Either you messed something up in one of your routing tables, or you messed up the far instance and it&#8217;s not forwarding correctly.</p>
<p>Also, don&#8217;t try and jam everything all into one security group, I think that gets messy. I use one Security Group which allows the VPN protocols, and another security group that grants access to inside-ey instances. A little neater that way, IMHO.</p>
<h3>Stage 3b: One and a half hops the other way</h3>
<p>Now repeat the same process starting with the Far gateway, to a Near instance. Same rules apply. You should be able to <code>ping</code>, or even <code>curl</code> or whatever other protocol that you want to be able to use across the VPN. You&#8217;ll be checking security groups and adding routing tables and so on as before, but this time for the far network onto the near VPC routing tables.</p>
<h3>Stage 3c: Two Full Hops</h3>
<p>This one is mostly to get you to feel better. Try pinging from your near-instance to your far-instance. It should work. And vice-versa.</p>
<h1>CONGRATS, YOU DID IT!</h1>
<h3>Stage ∞: Advanced</h3>
<h4>Resiliency</h4>
<p>Some stuff to think about &#8211; you have an entire VPN hinging on two crappy little AWS boxes. You sure you&#8217;re ok with that? I don&#8217;t think I am. Consider maybe spinning up another pair of boxes, and having redundant routes in your routing tables. Hopefully the AWS magic will let the remaining route take over for the broken one, if there is a break. But I would test that. Two redundant routes is near-useless if every other packet goes over a dead link.</p>
<h4>Routing</h4>
<p>Once you have enough point-to-point connections that you&#8217;ve set up, trying to maintain routing tables everywhere starts to become a pain in the ass. Consider implementing some routing. I would probably stay away from RIP, even though it&#8217;s really easy, because I would fear its routing tables might not converge fast enough. But, it&#8217;s also easy &#8211; so maybe I would at least give it a try. OSPF is another option, but does have some complexity to it. IS-IS makes you sound like you&#8217;re on a watchlist, but is another interior routing protocol. BGP is the big daddy here, but my impression of it was that it was better at large routing tables &#8211; like, uh, the Internet.</p>
<p>But I suspect, if you were able to get any of these working, any of them would be OK-ish. One concern I might have is that you can&#8217;t influence the AWS Routing tables from your instance; I don&#8217;t know exactly how that would work. Would you have to route <strong>all</strong> traffic down to your own internal router instance? That would suck.</p>
<h4>VPC VPN Gateway Service from AWS</h4>
<p>Amazon has a VPN Gateway service, but it is really designed to hook the VPN device you have in your office to your Amazon network. Why they would be so strangely short-sighted, I have no idea. But a lot of my experimentation was trying to get this service set up in my &#8216;spoke&#8217; networks, and then have a central network that is a pseudo-&#8220;Customer Gateway&#8221;. They support BGP and other stuff there, too. In trying to mess around with this, I had trouble because they really wanted some crazy <code>169.254.x.y/30</code> network to be either side of the gateway, and they want two tunnels per VPN Gateway device. Which is weird, because you only get one tunnel back as the &#8216;customer gateway&#8217; but, whatever. Anyways, there might be something here &#8211; and if you go with routing this might be the only way for you to go.</p>
<h1>Conclusion</h1>
<p>The AWS Marketplace was really, really, really embarrassingly bad when it came to this. The Linux documentation on what tools to use here is a total shambles. There are apparently two competing sets of userland tools &#8211; the blah-swan stuff and ipsec-tools. I basically went with the one that had more examples written and better documentation. There was lots of weird stuff on the AWS Linux (which is really CentOS). Like, if you followed their (quite lovely) documentation, you would get some bizarre hard failures, and googling didn&#8217;t get me anywhere.</p>
<p>If this is anything like the last time I did all kinds of crazy networking work in AWS, I will end up finding out that Amazon releases &#8220;Amazon EZ VPN Interconnect Service&#8221; in a few weeks for like 2¢ a month or something. Oh well. Until then, we have the stuff I listed above.</p>
<p>Hope I at least saved you a bit of time, if nothing else.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2017/11/creating-a-site-to-site-vpn-in-aws-between-regions/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Why I would seriously consider using Laravel instead of Rails for just about any web project</title>
		<link>https://uberbrady.com/2017/11/why-i-would-seriously-consider-using-laravel-instead-of-rails-for-just-about-any-web-project/</link>
					<comments>https://uberbrady.com/2017/11/why-i-would-seriously-consider-using-laravel-instead-of-rails-for-just-about-any-web-project/#comments</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Wed, 08 Nov 2017 03:07:46 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://uberbrady.com/?p=221</guid>

					<description><![CDATA[This is an opinion piece. The following is my opinion. I don&#8217;t need to yuck your yum; if you love Rails and you think Rails is great, then that&#8217;s awesome for you. I&#8217;ve had a lot of great experiences with it in the past. These are my thoughts, for me. I&#8217;m not stupid enough to &#8230; <a href="https://uberbrady.com/2017/11/why-i-would-seriously-consider-using-laravel-instead-of-rails-for-just-about-any-web-project/" class="more-link">Continue reading<span class="screen-reader-text"> "Why I would seriously consider using Laravel instead of Rails for just about any web project"</span></a>]]></description>
										<content:encoded><![CDATA[<p>This is an opinion piece. The following is my opinion. I don&#8217;t need to yuck your yum; if you love Rails and you think Rails is great, then that&#8217;s awesome for you. I&#8217;ve had a lot of great experiences with it in the past. These are my thoughts, for me. I&#8217;m not stupid enough to say &#8220;Rails Considered Harmful!&#8221; or anything stupid like that; it&#8217;s still a powerful, popular tool. But here are my thoughts about it:</p>
<p><span id="more-221"></span></p>
<p>I know a ton of languages. I know a decent number of frameworks. I have been working with Rails since like v1.0 or something.</p>
<p>I remember when I first started using it; it was <strong>amazing</strong>. All this stupid boring shit I had to do in PHP to get a database connection, grab results, put them on the screen, make forms around them &#8211; everything &#8211; could now get done in a ridiculously tiny fraction of the time. It was truly world-changing, and it made total sense that everyone was going nuts over it. As well they should.</p>
<p>Ruby, the language, is a bit slow. So what? Just run more servers. And I agree with that. I mean, if I can make my programmers just 2x as effective and make my server bill 10x as much, it&#8217;s still a steal. I have no problem with that math at all.</p>
<p>And there&#8217;s much to be said for the language and its elegance. Everything is an object. Classes are just more objects. Class methods and all kinds of other things are great too. Everything you would want to do to a string is a method in the String class. It&#8217;s really quite pleasant to read.</p>
<p>But I remember the first time I ran into something weird and magical in Rails that freaked me out. I was trying to troubleshoot why this one field kept outputting as a date, when it was actually a timestamp. I mean, the field&#8217;s name happened to be <code>date</code> but that was a legacy issue I just needed to live with. The name of a thing shouldn&#8217;t affect what type of thing it is, right? Eventually I renamed the field to <code>fuck_you_rails_you_piece_of_shit</code> and suddenly it began working. Too much magic.</p>
<p>But, still, I was far more productive with Rails than I was anywhere else. I&#8217;d looked into PHP frameworks at the time and they did not come remotely close. They seemed to just add complexity and not take anything away.</p>
<p>So I kept holding on to my toolset &#8211; Rails for anything with a decent amount of MVC-ish complexity; PHP for little one-or-two-pager apps that I need to bang out real quick. And that served me well.</p>
<p>That being said, Rails began to start to show some real problems for me. Upgrading an app I built from Rails 1 to Rails 2 was a pain in the butt, but I was able to do it once I spent enough time. Upgrading that app to Rails 3 was nearly impossible, and I had to just completely back out of the upgrade once I was around 6 hours in. The documentation was constantly changing. What was once <code>rake console</code> now suddenly became <code>rails console</code> and it&#8217;s not like the error messages were very clear about that either. A friend of mine tried to run through a Rails tutorial and had a horrible time of it, so he gave up. He wasn&#8217;t the best programmer in the world, but still. Keeping Rails running was also nightmarish, the best solution I had come up with at the time was Phusion Passenger, and that was OK. But getting code deployed was really difficult and generally very unpleasant. I was starting to feel like &#8220;Rails makes my developers 5 times more productive!&#8221; was still true, but conversely, &#8220;Rails makes my operations engineers 5 times less productive!&#8221; was also true.</p>
<p>And as Rails grew larger and more popular &#8211; and was still dog-slow &#8211; it started to have to add even more features around its miserable slowness. Rails got the Asset Pipeline. And support to push everything into CDN&#8217;s. Certainly, those are scaling issues that need to be handled, but Rails by default handled it sooner to try and make up some of that lost time. Now we have &#8220;Spring,&#8221; which means every command I type I have to preface with <code>DISABLE_SPRING=1</code> or else I get hard-to-debug errors and lose countless amounts of time. Another innovation Rails has had to add is Turbolinks &#8211; which I actually think is spectacular technology &#8211; but is yet another way to hide or bury the generalized sloweousity of Rails. And the previous version completely shat up my apps; we pulled it pretty quick. (Caveat: the new Turbolinks 5 is excellent, and I&#8217;m using it in production and really enjoying it).</p>
<p>At some point, somehow, I got introduced to Laravel. And Laravel is all the good things of Rails and fewer of the bad things.</p>
<p>Yes, it&#8217;s written in PHP, and PHP isn&#8217;t a &#8220;pretty&#8221; language. Shut the fuck up, we&#8217;re not painting beautiful renaissance canvasses here; we&#8217;re putting together some bullshit web app for someone who is giving us money. Yes, there are gotchas in PHP. There are gotchas in Ruby. I spent an hour troubleshooting why some really basic, obvious comparison was failing only to eventually determine that one variable was a <code>Symbol</code> and one was a <code>String</code>. Or I don&#8217;t know if you&#8217;ve ever tried to use <code>@@</code> class variables, but they&#8217;re confusing, weird, and I&#8217;m still not sure I understand them completely. Everything&#8217;s at least a little weird, everywhere. And another problem I keep running into (and this may be a community problem, not a language problem) is that everyone is so fucking busy jerking themselves off to how &#8220;Readable&#8221; and &#8220;Elegant&#8221; their code is that it slows them down &#8211; &#8220;Oh, should I write this as <code>do_something! unless @mything.foo?</code> or should I write it with an <code>if</code>&#8230;&#8221; and then they sit around with their thumbs up their asses trying to be these lovely hand-crafted artisan hipster douchewads. Sometimes too much syntactic sugar can lead to crushing decision-fatigue.</p>
<p>Laravel is fucking fast. I open up a Laravel console (called &#8220;Tinker&#8221;) on <a href="https://twitter.com/snipeyhead">Snipeyhead</a>&#8216;s <a href="https://snipeitapp.com">Snipe-IT project</a> and it pops open in a split-second. If I wanted to be distracted &#8211; and believe you me, I really do seem like I want to be &#8211; I couldn&#8217;t be. It&#8217;s just already there. Whatever thing I wanted to dick around with on the console I can just bang right out. And in general everything seems to be fast like that. We don&#8217;t have a <code>schema.rb</code> file in Laravel, because you don&#8217;t need it; you can rip through a massive directory of migrations in a ridiculously tiny amount of time. So there&#8217;s no <code>schema.rb</code> file to get out of sync with your other developers or any other such kind of miserable shitshow.</p>
<p>There&#8217;s a lot of cool stuff that saves you time, but it&#8217;s not so crazily magical that you can&#8217;t figure out what it does. When you want to say that something hasMany of something else, you just create a method named appropriately, and have it return <code>$this-&gt;hasMany('That')</code>.</p>
<p>Deployment is still harder than a boring old regular PHP app, but that&#8217;s mostly due to <code>composer</code> (PHP&#8217;s gem/bundler solution) &#8211; and I suspect that we gain much more from <code>composer</code> than we lose. I remember trying to grab PEAR libraries, and other ways of tracking down dependencies. Not fun. I can still deploy an app as complex as Snipe-IT in seconds, relative to the multiple-minutes-long-nail-biting that is the Rails apps that I work with.</p>
<p>So far my biggest pet peeve with Laravel is the namespacing. Everything has these god-awful backslashes everywhere. Every file you edit has like a bajillion <code>use</code> statements up front to load up all the namespacery. It&#8217;s annoying and ugly. And like in the early days of Rails, I still find myself occasionally digging through the Laravel source to try and figure out how something works, or what it does. But, for me, it still gets the job done much better, much quicker, and much less unpleasant than when I do something in Rails.</p>
<p>Oh, another Laravel peeve &#8211; I still don&#8217;t fully grok when I need to use <code>-&gt;get()</code> or not. I generally try it one way until it fails, then I try it the other way. And &#8220;when to use parentheses on relations&#8221; also confuses me. But, generally, I try it one way then the other and it eventually works.</p>
<p>And, as a side note, I suspect you can pull together PHP programmers for way cheaper than Rails folks. So it might actually even pay off!</p>
<p>But that&#8217;s not why I&#8217;d choose Laravel; I&#8217;d choose it because it&#8217;s fast, saves me time, makes sense, and generally makes me feel good while I&#8217;m using it.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2017/11/why-i-would-seriously-consider-using-laravel-instead-of-rails-for-just-about-any-web-project/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Mini Displayport to Thunderbolt 3 &#8211; Connect an Apple Cinema Display to a 2016 MacBook Pro &#8211; for $26</title>
		<link>https://uberbrady.com/2017/04/mini-displayport-to-thunderbolt-3-connect-an-apple-cinema-display-to-a-2016-macbook-pro-for-26/</link>
					<comments>https://uberbrady.com/2017/04/mini-displayport-to-thunderbolt-3-connect-an-apple-cinema-display-to-a-2016-macbook-pro-for-26/#respond</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Thu, 27 Apr 2017 23:47:25 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://uberbrady.com/?p=214</guid>

					<description><![CDATA[I am still pretty shocked that there&#8217;s still no all-in-one Apple-provided doodad to do this. And there are some articles but they don&#8217;t seem quite complete. So, here&#8217;s how I did it for around $26, using two devices on Amazon: This gets you from Thunderbolt 3 (via USB-C) to full-size Displayport. This gets you from &#8230; <a href="https://uberbrady.com/2017/04/mini-displayport-to-thunderbolt-3-connect-an-apple-cinema-display-to-a-2016-macbook-pro-for-26/" class="more-link">Continue reading<span class="screen-reader-text"> "Mini Displayport to Thunderbolt 3 &#8211; Connect an Apple Cinema Display to a 2016 MacBook Pro &#8211; for $26"</span></a>]]></description>
										<content:encoded><![CDATA[<p>I am still pretty shocked that there&#8217;s still no all-in-one Apple-provided doodad to do this. And there are some articles but they don&#8217;t seem quite complete.</p>
<p>So, here&#8217;s how I did it for around $26, using two devices on Amazon:</p>
<p><a href="https://www.amazon.com/gp/product/B017TZTLC6/ref=oh_aui_detailpage_o00_s00?ie=UTF8&amp;psc=1">This</a> gets you from Thunderbolt 3 (via USB-C) to full-size Displayport.</p>
<p><a href="https://www.amazon.com/gp/product/B014DV2RGG/ref=oh_aui_detailpage_o00_s00?ie=UTF8&amp;psc=1">This</a> gets you from full-size Displayport to Mini Displayport.</p>
<p>I could&#8217;ve <em>sworn</em> that the USB-C-to-Displayport adapter I picked up listed Displayport Alternate mode and all that jazz, but apparently not. Either way, it seems to work for me (?).</p>
<p>Also wish it supplied power on its own &#8211; it doesn&#8217;t &#8211; but I guess I can live without that. Sucks though.</p>
<p>&nbsp;</p>
<p><img decoding="async" class="alignnone size-medium wp-image-218" src="http://uberbrady.com/wp-content/uploads/2017/04/IMG_0133-300x225.jpg" alt="" width="300" height="225" srcset="https://uberbrady.com/wp-content/uploads/2017/04/IMG_0133-300x225.jpg 300w, https://uberbrady.com/wp-content/uploads/2017/04/IMG_0133-768x576.jpg 768w, https://uberbrady.com/wp-content/uploads/2017/04/IMG_0133-1024x768.jpg 1024w, https://uberbrady.com/wp-content/uploads/2017/04/IMG_0133-1200x900.jpg 1200w" sizes="(max-width: 300px) 85vw, 300px" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2017/04/mini-displayport-to-thunderbolt-3-connect-an-apple-cinema-display-to-a-2016-macbook-pro-for-26/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to make a multiplayer FPS that isn&#8217;t Battlefield or Call of Duty</title>
		<link>https://uberbrady.com/2016/11/how-to-make-a-multiplayer-fps-that-isnt-battlefield-or-call-of-duty/</link>
					<comments>https://uberbrady.com/2016/11/how-to-make-a-multiplayer-fps-that-isnt-battlefield-or-call-of-duty/#respond</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Fri, 18 Nov 2016 23:34:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false"></guid>

					<description><![CDATA[So those guys (BF, CoD, maybe even Overwatch) are super-huge. They don&#8217;t really have problems with scaling. Or, maybe, in some cases, they do? Here&#8217;s something I saw while playing Titanfall 2. First off, and I think this is a significant problem, they have a TON of datacenters, like around 8 or 10 within 100ms &#8230; <a href="https://uberbrady.com/2016/11/how-to-make-a-multiplayer-fps-that-isnt-battlefield-or-call-of-duty/" class="more-link">Continue reading<span class="screen-reader-text"> "How to make a multiplayer FPS that isn&#8217;t Battlefield or Call of Duty"</span></a>]]></description>
										<content:encoded><![CDATA[<p>So those guys (BF, CoD, maybe even Overwatch) are super-huge. They don&#8217;t really have problems with scaling. Or, maybe, in some cases, <a href="http://www.ubergizmo.com/2016/11/microsoft-refund-call-of-duty-windows-10-store/">they do</a>? </p>
<p>
Here&#8217;s something I saw while playing Titanfall 2. First off, and I think this is a significant problem, they have a <b>TON</b> of datacenters, like around 8 or 10 within 100ms of my location. So I&#8217;m on at, like 1AM Pacific. There are a couple hundred people active on my closest-location data center (Salt Lake City). There are a couple hundred on in Oregon (GCE1?). A couple hundred more in Oregon-2 (GCE2). But we&#8217;re having matching problems, and it&#8217;s taking longer than it should to start games, and I keep seeing the same people. Logically, I can see that during peak times, with a crazy-high number of players logged-in, you want everyone to be as close as they can to their own data center, and you want as many damned data centers as you can throw money at to get. But when not? We&#8217;re splitting too many players across too many data centers, all for the sake of the difference between 45ms and 65ms. As it got later and later (I am a bit of a night owl) I started to check out other servers, farther away. In many cases, numbers as low as zero. Ugh. There&#8217;s a real concern that you might have some people logging in, seeing just a few users, and giving up. That&#8217;s enormously dangerous.</p>
<p>
This is a really hard problem. Crazy hard. There are a lot of different ways to approach it, and as I was thinking about it, I thought I might&#8217;ve come up with a decent algorithm that might work. This is more of a thought experiment, me armchair-quarterbacking a problem that I&#8217;m sure the actual devs are already hard-at-work fixing. But anyways, here&#8217;s my idea:</p>
<p></p>
<ul>
<li>First off, instead of connecting to your closest data-center, you instead connect to one Grand Unified Centralized registration system. First come, first serve. And, yes, if you live 500ms away, your registration time will be 500ms older than someone else. Too bad, that&#8217;s life. A &#8220;registration consist of just an IP/serial/whatever, a version number, and the number of milliseconds of delay to <b>every</b> datacenter that exists.
<li>Now the server has a list of registrations, in time order. First, you grab the oldest registration. (Note the time, for keeping track of worst-case registration times). Grab the shortest datacenter from the list of datacenters. Walk through registrations in time order, trying to find (howevery many users you need for a game) users for whom that is also their closest datacenter.
<ul>
<li>Did that work? Then great. Shunt those &#8216;N&#8217; players off to a game hosted in that data center. Then repeat with the next oldest registration.
<li>Let&#8217;s say that <b>didn&#8217;t</b> work. Now, things get interesting. Of all the registrations you have, find the lowest-ranked first-choice. This, by the way, is the same method as <a href="https://en.wikipedia.org/wiki/Instant-runoff_voting">Instant Runoff Voting</a>. For anyone who had chosen that first choice, bump them to their second choice. That may include our candidate registration, itself.
<li>Now, repeat the attempt to match up our candidate. Keep eliminating the least-popular data center until you can find a match.
</ul>
</ul>
<p>
So that&#8217;s it. Here are some of the practical advantages and disadvantages of this system, and some weird side-effects:</p>
<p></p>
<ul>
<li>If there&#8217;s, like, a 10 minute wait (which there oughtn&#8217;t ever to be), some people could beat that time by being at the end of the queue, but being in a region that needs players. I think that&#8217;s OK.
<li>I _think_ this might be hard to parallelize. You&#8217;d have high contention for the oldest items in the queue; you&#8217;d have to have some kind of locking mechanism, or something. This algorithm works best if running in series. Maybe there are some sneaky ways to do it otherwise, but I don&#8217;t know how off the top of my head. Maybe grab batches of 1000 registrations, and working that way?
<li>Super-duper single-point-of-failure. You lose the centralized registration server, game over. Maybe you fall back to the &#8216;old&#8217; way? Or maybe you&#8217;re just down, and that&#8217;s it.
<li>I worry what might happen if you start getting to 10,000,000 players all online at the same time? Being unable to burn through those folks fast enough might become a problem. Maybe once your region gets &gt;1000 users on it, you let them just hit their local region? I don&#8217;t know?
<li>The centralized registration system does have one simple function: match players and bounce them over to their regions. So it has exactly-one job, and I can&#8217;t imagine a single &#8216;matching&#8217; taking more than a few hundred milliseconds or so?
<li>In terms of scaling and stuff, I would say that you should add capacity to a region when there are no free game servers available (or &#8216;game slots&#8217;). If new servers take a while to spin up, I&#8217;d be more liberal than that (maybe using an algorithm of &#8220;if there are less than &#8216;n&#8217; slots available, then add a server&#8221;).
<li>You can go completely nuts spinning up data centers. Until you get into the, like 1000&#8217;s or so, this algorithm ought to keep working pretty well.
<li>When there are only &#8216;n&#8217; people online, total &#8211; and they&#8217;re from all around the globe &#8211; they may end up having a bad time; high latency. That is life, too bad.
<li>There may be a point where you say, &#8220;Sorry, person, but you&#8217;re fucked. There&#8217;s no one close enough to you to play a game.&#8221; That would be a terrible result, but it could happen. It depends on where the barrier to &#8216;too many milliseconds&#8217; is.
<li>I&#8217;ve thought about ways to globalize the registration system, with some kinds of distributed databases or whatever. I don&#8217;t think the costs are worth it, but, maybe, you could do some kind of distributed database-ey thing. I don&#8217;t know.
<li>The registration data is pretty dang ephemeral. You could maybe do this with something like Redis, though some of the queries we&#8217;d be talking about doing might not work there.
<li>I&#8217;d probably have it set up so that if the centralized service blows up and loses all its data, the various game clients will all try and reconnect. Especially if the registration service uses an ephemeral data-store, this could happen.
</ul>
<p>Of course, there are so many &#8216;gotchyas&#8217; and caveats and potential failure modes, and all kinds of problems with networking and latency and who-knows-what. I don&#8217;t know if this system is harder to implement with those caveats or not.</p>
<p>
And I&#8217;m just some guy, not a brilliant algorithms person or some distributed programming guru. This could all be a horrible, disastrous mistake of a system. I doubt most armchair quarterbacks actually call spectacular plays when they&#8217;re watching their various football games. (Look, sports reference! Yay!)</p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2016/11/how-to-make-a-multiplayer-fps-that-isnt-battlefield-or-call-of-duty/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>JavaScript: Callbacks, EventEmitters, and Promises &#8211; which one to use?!?</title>
		<link>https://uberbrady.com/2016/10/javascript-callbacks-eventemitters-and-promises-which-one-to-use/</link>
					<comments>https://uberbrady.com/2016/10/javascript-callbacks-eventemitters-and-promises-which-one-to-use/#respond</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Thu, 20 Oct 2016 05:49:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false"></guid>

					<description><![CDATA[Short version If you have something that&#8217;s simple and always synchronous, don&#8217;t use any of them. Just write a dumb function. If you have a function that&#8217;s simple and only needs one asynchronous response &#8211; and there are no other potential responses &#8211; then a callback is fine. If you have some kind of object &#8230; <a href="https://uberbrady.com/2016/10/javascript-callbacks-eventemitters-and-promises-which-one-to-use/" class="more-link">Continue reading<span class="screen-reader-text"> "JavaScript: Callbacks, EventEmitters, and Promises &#8211; which one to use?!?"</span></a>]]></description>
										<content:encoded><![CDATA[<h1>Short version</h1>
<p>
If you have something that&#8217;s simple and always synchronous, don&#8217;t use any of them. Just write a dumb function.</p>
<p>
If you have a function that&#8217;s simple and only needs one asynchronous response &#8211; and there are no other potential responses &#8211; then a callback is fine.</p>
<p>
If you have some kind of object that could have several different potential asynchronous responses &#8211; at various different points in lifecycle &#8211; and you might or might not want to listen to none, one, or more of them? Then use <b>EventEmitters</b>.</p>
<p>
And finally, use Promises when:</p>
<ul>
<li>You have a collection of asynchronous functions, and you need to respond only when all of them have returned, or any one of them have returned.
<li>You&#8217;re doing mostly &#8216;imperative&#8217; functions and don&#8217;t need to pass a lot of values around, you just need to chain together some callbacks in sequence.
<li>You have some functions that might be synchronous, and some that might not be, and you&#8217;re not sure which until runtime
<li>You have a collection of asynchronous events that are all firing, but the order that they must complete in is dependent upon some value determined only at runtime.
<li>(weaker argument) You are falling victim to callback-hell, and your code is steadily creeping rightward
</ul>
<hr />
<h1>Long version</h1>
<h2>Functions</h2>
<pre><tt>
function foo(param1,param2,param3) {
  return "something";
}

//usage:
var a=foo(1,2,3);
</tt>
</pre>
<p>If you can do it this way your life will be better. Do it this way if at all possible.  </p>
<h2>Simple Callbacks</h2>
<pre><tt>
function foo(param1,param2,param3,callback) {
  process.nextTick(function () {
    callback("something");
  });
}

//usage:
foo(1,2,3,function (result) {
  console.warn("Yay, we got result! "+result);
});
</tt>
</pre>
<p>If you find you&#8217;re passing &#8220;callback1, callback2, callback3&#8221; definitely don&#8217;t do this. But for small, simple asynchronous functions, with not much else going on, this is still fine. Still pretty easy to reason about. As functions grow larger, and nested callbacks grow deeper, it gets harder and harder to reason about, though. The <i>invocations</i> of your little function probably ought not to be more than just a few lines; if they are, you should consider the next option&#8230;</p>
<p><h2>EventEmitters</h2>
<p>I think 95% of the EventEmitters I create end up being &#8216;classes&#8217; that extend the EventEmitter class, and I think that&#8217;s probably a good way to do it.</p>
<p><pre><tt>
   /* ..... */
   this.emit("begin","something");
   /* ..... */
   this.emit("success","something");
   /* ...... */ 
   this.emit("failure","something");
   /* ...... */
   this.emit("complete","something",success === true);
</tt>
</pre>
<p>What&#8217;s great about this model is that someone who&#8217;s <i>consuming</i> this object might only care about one particular event &#8211; in which case they can listen for just that one. I believe it&#8217;s ok, and actually good, to emit liberally, even events that are similar but not the same (in my example &#8220;success&#8221;/&#8221;failure&#8221; as well as &#8220;complete&#8221;).</p>
<p>Another nice side-effect is that all of your various listen events (<tt>.on(foo)</tt>) help document what the callback is actually <b>for</b>. E.g. &#8211;  </p>
<pre><tt>
on("complete",function (param) {
  /* see? Now we know this event handler fires when things are complete! */
});
</tt>
</pre>
<p>If you&#8217;re not careful, you can absolutely slide into callback-hell here. But this is my personal favorite pattern to use. It&#8217;s pretty extensible.</p>
<p>Never do synchronous callbacks; ever. If you want to do something &#8216;immediate&#8217; at least wrap it in a <tt>process.nextTick(function () {/* blah */});</tt> block; that&#8217;ll effectively be immediate but allow for someone to use it in the way most EventEmitters are used.</p>
<p>Never throw errors; just emit &#8220;error&#8221; instead.  </p>
<h2>Promises</h2>
<p>These are massively over-hyped as the solution to everything. While they are actually very, very cool; they definitely have some real drawbacks.</p>
<ul>
<li>They can get hard to debug
<li>They can be confusing
<li>missing something like a <tt>return</tt> &#8211; which is super-easy to do &#8211; may just cause silent code malfunctioning instead of issuing any kind of error
<li>Propagating data forward from previously-resolved promises into later promises looks and acts weird.
<li>You lose a lot of the benefits of &#8216;closing-over&#8217; variables
</ul>
<p>But, when used properly &#8211; they can turn something nasty like this:  </p>
<pre><tt>
foo.on("bar",function (baz) {
  bif.on("blorgh",function (bling) {
    bloop.on("gloob",function (fweep) {
      /* .... */
    });
  });
});
</tt>
</pre>
<p>Into something much prettier like this:  </p>
<pre><tt>
foo.bar().then(function (baz) {
  return "thing";
}).then(function(bling) {
  return "other_thing";
}).then(function (fweep) {
  return "last_thing";
});
</tt>
</pre>
<p>Which, especially if you end up with a super-long list, can be helpful.</p>
<p>You can also use <tt>.catch()</tt> to grab <i>any</i> error in your list of actions &#8211; and that can be enormously useful.</p>
<p>Also, if you have an array of promises, you can do something like &#8211;  </p>
<pre><tt>
Promise.all(my_array_of_promises).then(function (results) {
  /* do something */
});
</tt>
</pre>
<p>Which can be very, very handy.</p>
<p>Where it starts to get ugly is, if in that example I gave above <tt>foo.bar()....</tt> &#8211; if you need to treat an error condition for each of those steps slightly differently. Now you <b>can</b> throw various <tt>.catch</tt> statements after each <tt>.then</tt> statement, but I can imagine trying to visually read through that as being a nightmare.</p>
<p>The other huge thing here is that some promises can be fully synchronous &#8211; e.g. <tt>Promise.resolve(7)</tt> &#8211; that&#8217;s a promise that will resolve to the number 7. And some promises (well, probably most of them) are asynchronous. This is great, and the ability to unify these two modes together can be very helpful.</p>
<p>
So, absolutely use them when they make sense. But my current thinking (which might change) is that you should use the simplest asynchronous mechanism that expresses what you need, without adding complexity. Step up the complexities of your tech as you need to, but not before.</p>
<p>
<b>Use the right tool for the job.</b></p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2016/10/javascript-callbacks-eventemitters-and-promises-which-one-to-use/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>A pinko-commie lefty-liberal&#8217;s _technical_ argument against The Secretary of State using Her Own Email Server</title>
		<link>https://uberbrady.com/2015/08/a-pinko-commie-lefty-liberals-_technical_-argument-against-the-secretary-of-state-using-her-own-email-server/</link>
					<comments>https://uberbrady.com/2015/08/a-pinko-commie-lefty-liberals-_technical_-argument-against-the-secretary-of-state-using-her-own-email-server/#comments</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Mon, 31 Aug 2015 23:18:00 +0000</pubDate>
				<category><![CDATA[bad]]></category>
		<category><![CDATA[politics]]></category>
		<category><![CDATA[ugh]]></category>
		<guid isPermaLink="false"></guid>

					<description><![CDATA[If an employee of mine tried to send email from their own server, instead of using my company&#8217;s, I&#8217;d reprimand them, harshly. And if they continued to refuse to use the appropriate email server I&#8217;d have to terminate them. Why? Security. Who ran Hillary Clinton&#8217;s Email server? What software did it run? Where was it &#8230; <a href="https://uberbrady.com/2015/08/a-pinko-commie-lefty-liberals-_technical_-argument-against-the-secretary-of-state-using-her-own-email-server/" class="more-link">Continue reading<span class="screen-reader-text"> "A pinko-commie lefty-liberal&#8217;s _technical_ argument against The Secretary of State using Her Own Email Server"</span></a>]]></description>
										<content:encoded><![CDATA[<p>If an employee of mine tried to send email from their own server, instead of using my company&#8217;s, I&#8217;d reprimand them, harshly. And if they continued to refuse to use the appropriate email server I&#8217;d have to terminate them.</p>
<p>
Why? Security.</p>
<p>
Who ran Hillary Clinton&#8217;s Email server? What software did it run? Where was it hosted? How physically secure is that location? How secure is the ISP that serves data to that server? The administrators of that server &#8211; are they background-checked? Are we sure they are not in the service of any foreign entity, or even a domestic one? Is the server patched to the latest version? Are there any vulnerabilities on the version it <i>is</i> running? Are there any backdoors or rootkits or other such stuff on there? What&#8217;s the update schedule on that server? Is there any strong cryptography on it? What protocols are running?</p>
<p>
And the answer in just about all of these cases is, &#8220;I have absolutely no idea.&#8221; And that is completely and totally unacceptable.</p>
<p>If you administer an email server, <b>YOU CAN (usually) READ ANY EMAIL THAT IS ON IT</b>. When it&#8217;s some regular schmoe somewhere, that&#8217;s less of a big deal (but still something to be concerned about). When it&#8217;s the Secretary of State of the United States of America, that&#8217;s a bit of a bigger deal.</p>
<p>
If you are reading this and feeling like I&#8217;m not exactly right, go talk to your email admin. Ask them to read you your latest email &#8211; &#8220;just so you can see if your email software is working.&#8221; Let me know what you find.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2015/08/a-pinko-commie-lefty-liberals-_technical_-argument-against-the-secretary-of-state-using-her-own-email-server/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>How to do: Gulp + Browserify + Coffeescript + Sourcemaps + Uglify as of mid-2015</title>
		<link>https://uberbrady.com/2015/05/how-to-do-gulp-browserify-coffeescript-sourcemaps-uglify-as-of-mid-2015/</link>
					<comments>https://uberbrady.com/2015/05/how-to-do-gulp-browserify-coffeescript-sourcemaps-uglify-as-of-mid-2015/#comments</comments>
		
		<dc:creator><![CDATA[uberbrady]]></dc:creator>
		<pubDate>Sat, 30 May 2015 16:51:00 +0000</pubDate>
				<category><![CDATA[browserify]]></category>
		<category><![CDATA[coffee]]></category>
		<category><![CDATA[coffeescript]]></category>
		<category><![CDATA[gulp]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[sourcemap]]></category>
		<category><![CDATA[uglify]]></category>
		<guid isPermaLink="false"></guid>

					<description><![CDATA[I blew so much time on this, it&#8217;s crazy. I got it down to something simple and clean, finally. And it turns out the &#8220;recipes&#8221; section on the Gulp website pretty much had the answer already. I just needed to understand more about what I was trying to do in the first place. Note: You &#8230; <a href="https://uberbrady.com/2015/05/how-to-do-gulp-browserify-coffeescript-sourcemaps-uglify-as-of-mid-2015/" class="more-link">Continue reading<span class="screen-reader-text"> "How to do: Gulp + Browserify + Coffeescript + Sourcemaps + Uglify as of mid-2015"</span></a>]]></description>
										<content:encoded><![CDATA[<p>I blew so much time on this, it&#8217;s crazy.</p>
<p>I got it down to something simple and clean, finally. And it turns out the &#8220;recipes&#8221; section on the Gulp website pretty much had the <a href="https://github.com/gulpjs/gulp/blob/master/docs/recipes/browserify-uglify-sourcemap.md">answer</a> already. I just needed to understand more about what I was trying to do in the first place.</p>
<p>
<em>Note:</em> You need to install <b>coffeeify</b> to have it available as a transform!<br />
<code></p>
<pre>var gulp        = require('gulp');
var browserify  = require('browserify');
var source      = require('vinyl-source-stream'); //to 'rename' your resulting file
var uglify      = require('gulp-uglify');
var buffer      = require('vinyl-buffer'); // to transform the browserify results into a 'stream'

var sourcemaps  = require('gulp-sourcemaps');

gulp.task("your_target",function() {
  browserify({
      entries: ["./sample.coffee"],
      debug: true,
      extensions: [".coffee"],
      transform: ["coffeeify"] // npm install --save-dev coffeeify
      })
    .bundle()
    .pipe(source('resulting_file_name.js'))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: true,debug: true}))
    .pipe(uglify(/* {
          debug: true,
          options: {
            sourceMap: true,
          }
      }*/)).pipe(sourcemaps.write("./" /* optional second param here */))
    .pipe(gulp.dest('./build/'));

});
</pre>
<p></code></p>
<p>If you don&#8217;t want the sourcemap URL in your resulting JS file (which I didn&#8217;t, because I keep my sourcemap file private), add a second parameter <code>,{addComment: false}</code> to the <code>sourcemaps.write</code> line near the end.</p>
<p>
<em>Edit:</em> &#8211; the parameter to uglify isn&#8217;t even needed.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://uberbrady.com/2015/05/how-to-do-gulp-browserify-coffeescript-sourcemaps-uglify-as-of-mid-2015/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
	</channel>
</rss>
