Exact requirements for a salt depend on the password hashing algorithm, but for the usual methods (bcrypt, PBKDF2...) the only requirement is that the salt is unique. Or at least as unique as is practical; the odd collision is not a big issue as long as it does not happen often and cannot be forced from the outside.
Uniqueness is worldwide; it is not sufficient for salts to be unique in a given server. Two distinct servers, using the same hashing algorithm, should have distinct salts too.
A relatively common and cheap way to get worldwide uniqueness is to generate salts from a cryptographically strong PRNG, with sufficient length (16 random bytes are sufficient). That's what bcrypt does. If the PRNG is biased, then you need a somewhat longer salt to achieve uniqueness. If the PRNG is weak because of too small a seed or internal state, then uniqueness will not be satisfactorily obtained that way. The user name is not a good salt, for two reasons:
- The same user name can occur in several servers (e.g. each server might have an "Administrator" account, under that exact name);
- The user does not change his name when he changes his password, leading to salt reuse.
Salts are not the same thing than keys (which are secret and must remain confidential) or initialization vectors (IV are "starting points" for some algorithms, and may have additional requirements such as uniformness and unpredictability in the case of CBC encryption). There is normally no problem in giving away your salt values; anyway, whoever recomputes the hash value from the password must know the salt. Therefore, publication of salts is intrinsic with password-based encryption of files (the salt is then encoded in the file header). It is also necessarily published in authentication protocols where the hashing occurs on the client (that's quite rare in Web contexts, because Javascript is too slow). There is no point in needlessly publishing the salts, but keeping them secret does not really enhance security either.
In this answer, a fringe scenario is evoked: an attacker learns the salt beforehand, prepares a big precomputed table, then enacts the actual attack which reveals the password hash. This does not make it easier for the attacker to break the password; in fact, this increases his effort (he has to produce a full table instead of stopping when the password is found, so that's double cost on average; if the table is of the rainbow persuasion, an additional 1.7 factor enters for table generation; and there are storage costs). What it changes is the dynamics: this shortens the time between the break-in (the hash value is stolen) and the password recovery. This is an edge case, so don't sweat it. If you use password hashing for storage in an authentication protocol, where hashing occurs server-side, then you just store the salt with the hash value and the salts will be as confidential as the hash values themselves, and that's good. In other cases (e.g. password-based file encryption), salts will be more "public", but that's not critical in any way, so don't go about adding extra complexity to keep the salts secret (extra complexity is bad, and much worse than public salts).