Get Site URL from apex
#NotAnApi
But with some cunning, you can extract this from the site debug mode endpoint:
String name = 'mysite';
Site site = [
SELECT GuestUserId
FROM Site
WHERE Name = :name
];
String path = '/sites/servlet.SiteDebugMode';
PageReference pr = new PageReference(path);
pr.getParameters().put('guid', site.GuestUserId);
pr.getParameters().put('sitedebugmode', 'x');
String url = pr.getContent().toString().substringAfter('URL=').substringBefore(path);
System.debug(url); //eg "http://dev-bigass.cs81.force.com/mysite"
Seems to behave across environments regardless of Production / Sandbox / My Domain etc.
Since Winter '17 (v38.0)
You can get the secureURL using the SiteDetail object
Site mySite = [select Id from Site where Name = 'MySite'];
SiteDetail mySiteDetail = [select SecureURL from SiteDetail where DurableId = :mySite.Id];
System.debug(mySiteDetail.SecureURL);
This doesn't seem to be possible from apex, I ended up trying the different ways described above, and decided to go with a Custom Setting. I added the Custom Setting Site URL
which needs to be filled in every time when the app gets configured.